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で現在参加しているドメインの各メンバーのパスワード期限を取得する。
下記記事で環境構築しておきながら全部どっとねっとで済ましてしまった。
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. インストール
- Download Windows 7 Service Pack 1 (SP1) 用のリモート サーバー管理ツール from Official Microsoft Download Center ** Windows6.1-KB958830-x86-RefreshPkg.msu
2. 機能の有効化
Windowsの機能の有効化または無効化 ココ!
確認
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%; }
なんか右の白いエリアが余分でもうちょっと詰まらないか、とか
幅を狭くしていったら要素が重なっていく!とか
色々足らない部分があるんですが、とりあえず反映。