くろねこ自由気ままな日記

趣味の話題や忘備録(的な)情報のページ

ブログランキング・にほんブログ村へ

第3回 バッチ特集 ~指定日時にバッチを実行しよう!~


おはようございます。くろねこです。

はじめに、今回の記事は【講釈】が非常に多いです。すみません。
そこで、そのまま利用可能なバッチ(以下)を2本掲載します。
① 日時チェック用バッチ
② 日時設定用バッチ

注意事項にしたがって利用することで、バッチの実行制御が可能になります。

手っ取り早く使ってみたい方は、目次から「日時チェック用バッチの動作構成図」をクリックしてください。

 

【ご注意】
本サイトを参考に作成したものは、自己責任でお願いします。
実行前のレビューやテストを必ず実施してください。

それでは、今回もよろしくお願いします。

【講釈】はじめに

日時チェック用バッチ は、純粋にバッチの機能のみで作成したものです。
C#vbscriptなどで作ったほうが、もっと簡単に作成できますが、ここで掲載したのは、
ハッチだけでここまでできる!
のサンプル的な意味あいが強いからです。
バッチでできることは限られていますが、工夫することでここまでできるのです。

本当はもっと簡単に と思っていたのですが、テストをしてみると「雑」な部分が露呈し、途中からは、半分意地になってしまいました(笑)

【講釈】タスクスケジューラではだめなの?

ところで、日時チェック用バッチなんか作らなくても、タスクスケジューラでいいんじゃないの?
と思う方、多いでしょうね。


タスクスケジューラ

普通なら、特定の日時に処理を実施するには、Windowsではタスクスケジューラを利用しますが、くろねこの経験上、確実に運用する場合には、もっと簡単に実施できなければならないことが多かったのです。

【講釈】続きます m(_ _)m

【講釈】日時指定実行の必要性

運用の現場では、よくあるシチュエーションとして、以下のようなことがあります。
① 特定の日時(深夜や休日など)にある処理を1回だけ実行したい
② 定期的に処理を実施したい
③ 必要なタイミングで、ある処理を実施したい(タイミングは不定期)

言葉にするとわかりにくいですね。
ということで、具体的な例で言うと以下のようなケースです。

①は    「○月□日 深夜0:00 に c:\task\task0001.bat を実行する」
このケースは、ユーザのいない時間帯にサーバをリブート(再起動)したいときなどです。

②は    「毎週日曜日 深夜2:00 に c:\task\task0002.bat を実行する」
このケースは、おもにバックアップなどの用途になります。

③は    「次回は、○月□日 22:00 に、c:\task\task0003.bat を実行する」
このケースは、例えばですが
データの登録は都度実施していて、それらのデータのうち、有効日が ○月□日 22:00 のものを c:\task\task0003.bat で他のシステムへ連携させる みたいなものです。
「必要なタイミング」が「データ有効日」、「c:\task\task0003.bat」の内容が「別のシステムに連携する」にあたります。

これら3つのケースの作業の流れは下記のようになります。

①は、1回限りのタスクとなりますので、実行するプログラムの作成とタスクスケジューラでのタスク登録という流れになります。
これは、一発勝負となりますので、入念なレビューで対応するしかありません。

②は、①と同様に実行するものの作成とタスクスケジューラでのタスク登録でほぼ同じ流れになります。(繰り返し設定の違いのみ)
こちらのケースも基本的に①と同じですが、定期的に実行するものですので初回に問題があったとしても補正の余地があります。
とは言っても初回で正しく動作するようしっかりレビューですね。

問題は③のケースです。
初回は①のケースと同様に、
1回のみ実行のタスク、実行するプログラムの作成とタスクスケジューラでのタスク登録という流れは同じです。
ですが、「必要なタイミング」が決まった段階で、タスクスケジューラを開き、1回目で登録したタスクの実行日時を変更することになります。
それ以降、実行タイミングが決まる都度、実行日時の変更作業を実施しなければなりません。

【講釈】うまく動作しない!?

しかし、このタスクスケジューラでタスクを登録したが、目的の日時に実行されていなかった経験をお持ちの方、多いのではないでしょうか。

だから、
うまく動作しないリスクを極力低くするために、
必要以上であっても、最大の権限(管理者権限)で動作するように設定することが現場では多くなります。

当然ですが、管理者権限で動作するタスクの登録は管理者アカウントでWindowsにログオンしての操作となります。
要するに、タスクを確実に動作させるためには、最大限の権限でWindowsを操作したほうが楽なのです。
それが、多少のセキュリティリスクを含んでいたとしても・・・


管理者権限で実行

【講釈】日々の運用の中で

上記①~③において、タスク登録は十分な経験をもった方が実施されると思います。
多くの場合、一連の処理をひとつのバッチにまとめ、そのバッチをタスク登録するのが一般的です。

しかし、通常のプログラム作成ほど十分な「設計」をすることなく、「さらっと」バッチを作成するため、どういう思いでそのバッチが出来上がったのか? が残っていないことがほとんどなんです。

だから、一度、動かしたものは極力触りたくないのです。

ましてや、他人のバッチなんて触りたくもないし、自分のものを触らせたくもありません。

以上のことから、
①~③のタスク登録
 タスク登録(バッチ作成を含む)をする人
  → バッチの先で動くプログラムの設計者・製作者 (十分な経験あり)
 タスク登録(バッチ作成を含む)をするタイミング
  → 時間的にも精神的にも余裕があるときに実施する。(バッチ内にコメントを残す)

③の2回目以降の実行日時登録
 タスクの実行日時変更をする人
  → 初回タスク登録者がベスト
  → 他の人が実施する場合、設定変更後に初回タスク登録者による設定内容の確認

何れの場合も、タスク化ができていない場合は、
プログラムの設計者・製作者が作成した手順をメモ帳などで具体的に箇条書きし、実行タイミングになったら、手作業で処理することになります。
のちに、タスク登録(バッチ作成)の段階で、そのメモが設計書の役割となります。

と、まあ、こんな感じでやってますが

作業のピーク時となると、思わぬところで、つまらんミスが起きてしまいます。
特に、③の2回目以降の日時設定時で、一度、正常動作している安心感からか、軽く操作してしまうのです。
しかも、よりによってというタイミングで操作ミス
管理者権限でWindowsを操作、何気ない操作でミスを・・・


思わぬ大事故が

たった、日時を変更するだけだったのに・・・

【講釈】不安要素を減らすために

この日時を変更するだけの操作
もっと簡単に、確実にできないものでしょうか?

もっと言えば、
管理者アカウントのパスワードを教えたくなかった別のメンバへの作業分担できないものでしょうか?

ということで、
・ 実行したい日時のみを指定する
・ 管理者権限が無くても日時を指定できる
この2点を実現するために、今回の 日時チェック用バッチ を利用することで実現できます。

日時チェック用バッチの動作構成図

日時チェック用バッチを利用したタスクの動作構成図です。


日時チェック用バッチの動作構成図

関連するファイルは以下の表をご覧ください。


関連ファイル一覧表

日時チェック用バッチ(CheckDateTime.bat)

日時チェック用のメインとなるバッチファイルです。

バッチのコード

以下が、日時チェック用バッチ です。
コード部分をダプルクリックすると全選択されますので、コピーし、テキストエディタ(メモ帳など)貼り付け、CheckDateTime.bat という名前で保存してください。
文字コードANSIです。
保存先は、この後、説明する タスク実行用バッチ と同じフォルダにしてください。

@echo off
rem *****************************************************
rem 	CheckDateTime.bat
rem 	バッチで日時を確認するサンプル
rem 	日時チェック用ファイルに記述された日時と
rem 	指定日時を比較した結果を終了コードとして返却する。
rem 		終了コード	比較結果
rem				0		指定日時 ≧ 日時チェック用ファイルの日時
rem						(チェックファイルの日時を過ぎた)
rem				8		指定日時 < 日時チェック用ファイルの日時
rem						(チェックファイルの日時より前)
rem				12		日時チェック用ファイルが存在しない
rem				16		引数なし
rem *****************************************************

	cd /d %~dp0
	set @Log=%~n0.log
	echo %~n0 started : %date% %time% > %@Log%
	set @RC=0

:ChkParam
	echo :ChkParam >> %@Log%
	if "%1"=="" goto Usage
	set @ChkDtTmFile=%1
	set @dt01=%2 %3
	if "%time:~0,1%"==" " (
		set @time=0%time:~1%
	) else (
		set @time=%time%
	)
	if "%2"=="" (
		echo Check date time is current date time >> %@Log%
		set @dt01=%date% %@time:~0,5%
	) else (
		if "%3"=="" (
			echo Check date time is current time >> %@Log%
			set @dt01=%2 00:00
		)
	)
	goto ChkFile

:Usage
	echo.
	echo :Usage >> %@Log%
	echo * %0 usage **********************************
	echo %0 日時チェック用ファイル 比較する日付 時刻
	echo.
	echo	日時チェック用ファイルには、1行目に下記の形式で日付時刻情報を記述してください。
	echo	yyyy/mm/dd hh:mm
	echo.
	echo	比較する日付 時刻 は下記の形式で指定してください。
	echo	yyyy/mm/dd hh:mm
	echo.
	echo e.g.
	echo    %0 checkfile.txt 2022/09/01 13:00
	echo		2022/09/01 13:00 とファイルに記述された日時を比較する場合
	echo    %0 checkfile.txt
	echo		現在の日時とファイルに記述された日時を比較する場合
	echo 	(比較する日付のみ指定した場合、時刻は0:00として扱われます。)
	echo.
	set @RC=16
	goto Ending

:ChkFile
	echo :ChkFile >> %@Log%
	if exist %1 goto chkdate
	echo %1 が見つかりません。
	echo %1 が見つかりません。 >> %@Log%
	set @RC=12
	goto Ending

:ChkDate
	echo :ChkDate >> %@Log%
	rem Read first record only
	for /f "usebackq delims=" %%t in (%@ChkDtTmFile%) do (
		set @dt02=%%t
		goto Compare
	)

:Compare
	echo :Compare >> %@Log%
	echo Check File : %@dt02% >> %@Log%
	echo Compare :    %@dt01% >> %@Log%
	if "%@dt01%" geq "%@dt02%" (
		set @RC=0
		del %@ChkDtTmFile%
		goto Ending
	)
	set @RC=8
	goto Ending

:Ending
	echo :Ending >> %@Log%
	echo Return code : %@RC% >> %@Log%
	echo %~n0 ended : %date% %time% >> %@Log%
	set @dt02=
	set @dt01=
	set @time=
	set @ChkDtTmFile=
	set @Log=

	exit /B %@RC%

	set @RC=

保存したフォルダをコマンドプロンプトで開き、
CheckDateTime (リターン)
としたときに、下記のように表示されれば、問題ありません。表示されない場合は文字コードが間違っています。


CheckDateTime.bat 引数なしで実行した状態

バッチの使用方法

日時チェック用バッチは、
引数で指定された、実行日時ファイル に記載された 日付と時刻 とバッチ実行の日時を比較します。
結果はバッチの終了コード(ERRORLEVEL)で通知されます。
結果は下記4パターンてす。
0 : 指定日時を経過した
8 : まだ、経過していない
12: 実行日時ファイルが存在しない
16: 引数なし

日時チェック用バッチ の使い方は以下のようになります。

	cmd /c .\CheckDateTime.bat 実行日時ファイル
	if errorlevel 8 (
		goto ending
	)

	(メイン処理:指定時刻になった場合の処理)

:ending

日時設定用バッチ (SetDateTime.bat)

実行日時ファイルを作成するためのバッチファイルです。

バッチのコード

以下が、日時設定用バッチ です。
コード部分をダプルクリックすると全選択されますので、コピーし、テキストエディタ(メモ帳など)貼り付け、SetDateTime.bat という名前で保存してください。
文字コードANSIです。
保存先は、タスク実行用バッチの実行日時を設定する人のPCの任意のフォルダになります。
ショートカットをデスクトップに作っておくと便利です。

@echo off
rem *****************************************************
rem		SetDateTime.bat
rem		日時チェックバッチ用の実行日時ファイル作成用バッチ
rem *****************************************************

	cd /d %~dp0

	set @Log=.\%~n0.log
	echo Executed : %date% %time% > %@Log%

	set @output=\\SERVER\SHARE\SampleTask.txt

	if not exist %@output% goto inpdate

	echo.
	echo 既に実行日時が登録されています。(下記)
	echo 処理を続行する場合、実行日時は上書きされます。
	type %@output%
	echo.
	set /p @check="続行する場合は そのままEnterキー、キャンセルの場合は 他の文字 + Enter です。"

	if not "%@check%"=="" goto cancel
	echo.

:inpdate
	echo :inpdate >> %@Log%
	echo 処理実行日時を指定してください
	set /p @dttm="入力は yyyy/mm/dd hh:mm 形式です >>> "

	echo.
	echo %@dttm% に処理を実行します。よろしいですか?
	set /p @check="続行する場合は そのままEnterキー、キャンセルの場合は 他の文字 + Enter です。"
	if not "%@check%"=="" goto cancel

	rem 指定日時を出力
	echo %@dttm%> %@output%
	echo.
	echo 指定日時を %@output% に出力しました。
	goto ending

:cancel
	echo :cancel >> %@Log%
	echo 処理を中止しました。
	echo.

:ending
	echo :ending >> %@Log%
	set @output=
	set @check=
	echo.

	pause

バッチの使用方法

保存したフォルダをコマンドプロンプトで開き、
SetDateTime (リターン)

あとは、バッチが指示する内容にしたがって、操作をすれば、実行日時ファイルが生成されます。

タスク実行用バッチ (SampleTask.bat)

本来、ユーザが特定の日時に実行したいタスクのバッチファイルになります。
ここでは、本来実施したい部分(「メイン処理」)がダミーとなっているファイルです。
動作テストが終わったら、ダミー部分を本物の処理に書き換えてください。

バッチのコード

@echo off
rem *****************************************************
rem		SampleTask.bat
rem		サンプルタスク実行用バッチ
rem *****************************************************

	cd /d %~dp0
	echo %~nx0 start at %date% %time% > %~n0.log
:wait10s
	echo 10秒時間調整します >> %~n0.log
	timeout /T 10 /NOBREAK
:setparam
	echo setparam >> %~n0.log
	set @StartTm=%time%
	set @ExecDateTime=\\SERVER\SHARE\SampleTask.txt
:chkexec
	echo chkexec >> %~n0.log
	cmd /c .\CheckDateTime.bat %@ExecDateTime%
	if errorlevel 8 (
		echo 指定時刻になっていません >> %~n0.log
		goto ending
	)
	echo メイン処理を開始します >> %~n0.log
	rem *** メイン処理 ここから ******************************************************

	rem *** メイン処理 ここまで ******************************************************
	echo メイン処理が終了しました >> %~n0.log
:ending
	echo ending >> %~n0.log
	set @EndTm=%time%
	echo %~nx0 end at %date% %time% >> %~n0.log
	echo Start time : %@StartTm%, End time : %@EndTm% >> %~n0.log

	set @ExecDateTime=
	set @Work=
	set @StartTm=

	exit /B

rem ** Sub routine **********************************************************************
:trim
rem	Function : trim specified parameter 
	set @work=%1

バッチの使用方法

タスクスケジューラで、SampleTask.batを実行するタスクを登録します。
タスク登録については要点のみ記載します。

・ 基本タスクの作成
・ 名前設定
・ タスクトリガー
 毎日 開始日:任意 時刻:0:00
 繰り返し間隔 1時間
・ 操作 プログラムの開始
 プログラム/スクリプト SampleTask.batの完全パス名
 開始(オプション) SampleTask.batが保存されたフォルダ

おわりに

かなり長文の記事になってしまいました。
ここまで、ご覧いただき、ありがとうございます。

ここで、ちょっとだけ
タスクスケジューラでのタスク起動は実際には指定時刻よりも前に起動されてしまうケースがあります。

例えば、10:00:00に起動するタスクですぐに時刻を表示してみると、 9:59:59 だったりすることがあるのです。

くろねこの経験上では、最大5~7秒の場合もありました。
時刻を見ながら動作するようなタスクの場合は致命的なケースにつながる可能性もあります。
注意が必要です。

この対策は、タスク起動されたバッチの冒頭で10秒程度、時間調整することで回避できます。

それでは、また。


くろねこ自由気ままな日記

バッチ特集の過去の記事は下記をクリック願います。

www.kuronekofreedom.com

 

PVアクセスランキング にほんブログ村

ブログランキング・にほんブログ村へ
© 2020 くろねこ自由気ままな日記