命名って難しい

変数、関数、クラスなどなど実装より命名に毎回悩むタイプの人間による技術についてのメモ。

BCPコマンドで同一構造のサーバーのテーブルを比較する。

作ったのでメモ。

経緯

DBサーバーを入れ替える時、全データが入替えられているか確認する作業があったのですが、
「SSMSでSelectして目視比較して・・・」みたいな話が持ち上がり初めていたので必死で書きました。

どう考えても目視はやばい。

構造

以下の2ファイルを同一ディレクトリに用意して使います。

  • このバッチ
  • DB名とテーブル名を持つCSV

以下のように処理してDBのデータを比較します。

  • 新旧サーバーの対象のテーブルに対してBCPでエクスポート
  • エクスポートの結果をfcコマンドで比較。fcのログを出す。
    • 同一なら先頭にok
    • 相違なら先頭にngがつく

バッチのソース

@echo off
setlocal

pushd %~dp0

rem DBとテーブルのリストファイル名
set targetList=

rem ユーザーのアカウント
set OldSvrUser=
set NewSvrUser=
set OldSvrPass=
set NewSvrPass=

rem 比較サーバーインスタンス
set OldServer=
set NewServer=

rem 出力先フォルダ
powershell -Command "$(Get-Date).ToString('yyyyMMdd_HHmmss')" > %temp%\ret
set /p ymd=< %temp%\ret
set BaseFolder=%UserProfile%\Desktop\SvrDataComp\%ymd%\
set OldFolder=%BaseFolder%Old\
set NewFolder=%BaseFolder%New\

mkdir %BaseFolder%
mkdir %OldFolder%
mkdir %NewFolder%

rem 指定のリストからループして出力
for /f "tokens=1,2* delims=," %%i in (%targetList%) do (  
    call :CompareOldNewServer %%i %%j
)

popd
endlocal
exit

rem --------------------------------------------------------------------------------------
rem エクスポート処理
rem --------------------------------------------------------------------------------------
:ExportTable

rem 引数
set instance=%1
set db=%2
set table=%3
set exportPath=%4
set usr=%5
set pass=%6

TITLE Exporting [Server:%instance% DB:%db% Table:%table%]
bcp "SELECT * FROM %db%.dbo.%table%" queryout %exportPath% -S %instance% -U%usr% -P%pass% -w -k -o %exportPath%.log

exit /b

rem --------------------------------------------------------------------------------------
rem 新旧サーバーのテーブルのエクスポートと比較
rem --------------------------------------------------------------------------------------
:CompareOldNewServer

rem 引数
set db=%1
set table=%2

set  fileName=%db%_%table%.txt
set  oldExport=%OldFolder%%fileName%
set  newExport=%NewFolder%%fileName%


call :ExportTable %OldServer% %db% %table% %oldExport% %OldSvrUser% %OldSvrPass%
call :ExportTable %NewServer% %db% %table% %newExport% %NewSvrUser% %NewSvrPass%

set  compFile=%BaseFolder%ng_%db%_%table%.txt
fc  /a /c /n /u %oldExport% %newExport% > %compFile% 

if "%errorlevel%"=="0"  move %compFile% %BaseFolder%ok_%db%_%table%.txt
exit /b

Powershellでバッチ処理の時に日時をらくに取得する。

powershell -Command "$(Get-Date).ToString('yyyyMMdd_HHmmss')" > %temp%\ret
set /p ymd=< %temp%\ret

.Netに慣れているため、このスタイルで日付にできると楽でいいですね。

あと最近TEMPフォルダに結果をリダイレクトして変数に戻してくる方法が楽で使ってます。

直接代入できればいいのになぁ。

PowerShellで現在参加しているドメインの各メンバーのパスワード期限を取得する。

下記記事で環境構築しておきながら全部どっとねっとで済ましてしまった。

notshown.hatenablog.jp

SamAccountNameと残り日数CSV出力にしてなんやかんやする予定。

ソースコード

Add-Type -AssemblyName System.DirectoryServices
Add-Type -AssemblyName System.DirectoryServices.AccountManagement

$context  = New-Object System.DirectoryServices.AccountManagement.PrincipalContext( [System.DirectoryServices.AccountManagement.ContextType]::Domain, [System.Environment]::UserDomainName)
$up       = New-Object System.DirectoryServices.AccountManagement.UserPrincipal($context)
$searcher = New-Object System.DirectoryServices.AccountManagement.PrincipalSearcher($up)
$allUsers = $searcher.FindAll()

foreach($user in $allUsers){
    # 有効なアカウントのみ
    if($user.Enabled) {
        $deUser = [System.DirectoryServices.DirectoryEntry]$user.GetUnderlyingObject()
        $expDate = ([System.DateTime]$deUser.PasswordExpirationDate)

        # 今から期限までの期間を取得
        $ts = New-TimeSpan (Get-Date) $expDate

        # とりあえず前後10日の期間で計算する。
        if ( $ts.Days -lt 10 -and $ts.Days -igt -10 ){
            Write-Output ([string]::Join(",", @( $user.SamAccountName, $ts.Days)))
        }
    }
}

Windows7にPowerShell用のActiveDirectoryモジュールをインストールする。

ADサーバーにデフォルトでインストールされているPowershellのADモジュールをWindows7でも使いたい。

手順

手順については以下のURLを参照した。というかそのままです。

How to add Active Directory module in PowerShell in Windows 7 – SharePoint and Others

1. インストール

2. 機能の有効化

Windowsの機能の有効化または無効化 ココ! f:id:NotShown:20160830111706p:plain

確認

Windows Powershell ISEのコマンドエクスプローラ?にてモジュールにActiveDirectoryがあればOK

PowerShellで実行中のPCのActive Directoryのパスワード期限を取得する。

ADのモジュールはADサーバーしかインポートできないみたいですね。
ということで.Netを利用して作りました。

Add-Type -AssemblyName System.DirectoryServices
$adPath = [string]::Format("WinNT://{0}/{1}", [System.Environment]::UserDomainName, [System.Environment]::UserName)
$de = New-Object System.DirectoryServices.DirectoryEntry $adPath

# パスワード期限の取得
$expDt = [System.DateTime]$de.PasswordExpirationDate
echo $expDt

# 差分を取得
$ts = New-TimeSpan (Get-Date) $expDt
echo $ts

タスクスケジューラのタスクの名称変更をするバッチ

概要

タスクスケジューラのタスク名変えられないかゆい所に手が届くと素敵だと思いませんか。

実際はエクスポートして新しい名前でインポートして古い方を削除してます。

実装

ソースコード

@echo off

setlocal
set tempTask=%temp%\tmptask
set oldName=%1
set newName=%2

rem 引数チェック
set result=エラー: 引数不正[空文字]
if "%oldName%" == "" ( goto :EchoResult )
if "%newName%" == "" ( goto :EchoResult )

if %oldName% == %newName% (
  set result=エラー: 引数不正[変更前後が同一名称]
  goto :EchoResult
)

rem クエリによる出力
schtasks /Query /XML /TN %oldName% > %tempTask%
if not %errorlevel% == 0 (
  set result=エラー: タスクのXMLエクスポート失敗
  goto :EchoResult
)

rem 新規タスクのインポート
schtasks /Create /XML %tempTask% /TN %newName%
if not %errorlevel% == 0 (
  set result=エラー: タスクのXMLインポート失敗
  goto :EchoResult
)

rem 命名変更前のタスクの削除
schtasks /Delete /F /TN %oldName%
if not %errorlevel% == 0 (
  set result=エラー: 名称変更前のタスクの削除失敗
  goto :EchoResult
)

set result=タスクの名称変更完了

:EchoResult
echo %result%

endlocal
exit

使い方(RenameTask.batというファイルで作った前提)

RenameTask.bat  *変更対象のタスク名* *変更後のタスク名*
  • 変更対象のタスク名

    • 変更対象のタスク名。
    • タスクスケジューラの直下で作ればそのままの名前。
    • フォルダを作った中のタスクの場合はフォルダ名も含めて指定すること。
    • 例:Automations\すこし自動化するタスク
  • 変更後のタスク名

    • 変更後のタスク名。
    • 変更対象のタスク名と同様、フォルダを考慮した指定をしてください。
    • 例:Automations\すごく自動化するタスク

参考(technet)

タスクをエクスポートする

タスクをインポートする

タスクを削除する

適当感想

こういう作ったバッチのコマンドライン引数とかを説明する時の定石っていうかうまい書き方ってあるのかなぁ。
ちょっとスタイル出来上がってないので既存のベストプラクティスが欲しい。

以上!

デザインテーマ:Naturalのデザインを2カラムにカスタマイズした。

タイトルで全部説明しきってしまった。
自分でブログから記事を見直す時に最近の投稿など、あの部分が右に来ると丁度いいなと思ったのでWeb系最近触れ初めた自分ができるだけのことをしました。

以下、カスタマイズCSSに記述した内容。

#container {
  width: 80%;
  overflow:auto;
}
#wrapper {
  float:left;
  width:70%;
}
#box2 {
  float:left;
  width:10%;
}

なんか右の白いエリアが余分でもうちょっと詰まらないか、とか
幅を狭くしていったら要素が重なっていく!とか

色々足らない部分があるんですが、とりあえず反映。