検索
連載

誤解しているのは中の人? Windowsの「曜日」の話 〜その2〜その知識、ホントに正しい? Windowsにまつわる都市伝説(144)

Windowsの「タスクスケジューラ」における曜日指定のスケジュールされたタスクは、利用者側の誤解やソフトウェアのバグが原因で、意図しないタイミングで実行される場合があります。また1つ、謎のバグが存在する可能性が明らかになりました。

PC用表示 関連情報
Share
Tweet
LINE
Hatena
「Windowsにまつわる都市伝説」のインデックス

Windowsにまつわる都市伝説

「曜日」の誤解と「タスクスケジューラ」の信じ難いバグ

 本連載第136回では、Windows Updateの定例更新日の誤解、それに絡めてWindows 10 バージョン1803以前のWindows 10、および対応するバージョンのWindows Serverに存在した「タスクスケジューラ」の謎のバグについて紹介しました。

 第136回では、Windows Updateの毎月定例の更新日は「第2火曜日固定」にもかかわらず(日本では時差の関係で翌水曜日)、「第2水曜日」と勘違いしている人がいることを指摘しました。また、それに絡めて毎月(または毎週)の曜日指定でスケジュールされたタスクにある、よくある誤解について指摘しました。その誤解とは、タスクスケジューラには「第N曜日」(Nは1〜4、または最終)という指定はあっても、「第N週」という指定はそもそも存在しないということです。

 しかし、Windows 10 バージョン1803以前のWindows 10、および対応するバージョンのWindows Serverには、長い間、謎のバグが存在し、その誤解を助長させていたかもしれないことを指摘しました。“謎のバグ”とは、曜日指定でスケジュールされたタスクが、実行日が7の倍数のときにタスクが実行されなかったり、1週間前に実行されたりするという信じ難いバグです。このバグは、2018年9月の更新プログラムで修正済みです(Windows 10 バージョン1511および1703は修正の予定なし)。

 2019年8月21日、Japan Windows Commercial Supportフォーラムが、Windowsの一部のバージョンに存在する、また別の謎のバグについて情報を公開しました。今度の謎のバグとは、曜日指定のタスクが、前の曜日(つまり前日)に実行される場合があるというものです。

 このバグが影響するのは、以下の4つの条件を全て満たす場合だそうです。おそらく、Windows 10バージョン1607の全てのエディションに影響すると思いますが、LTSBではなく半期チャネル(SAC)バージョンは既にサポートが終了しているため、含まれないのでしょう。当面の回避策は、日本時間(JST)AM9:00以外に少しずらすこと(例えば、AM8:59)が案内されています。

(1)Windowsのバージョンが以下であること

    Windows 8.1/Windows Server 2012 R2

    Windows 10 Enterprise 2016 LTSB/Windows Server 2016

    Windows 10 バージョン1903

(2)2019年3月第3週以降の更新プログラムが適用されていること(Windows 10 バージョン1903はリリース時から)

(3)毎週や毎月の指定された曜日に実行するタスクであること

(4)タスクの実行時間が日本時間(JST)AM9:00(UTC 0:00)であること


 第136回では、Windows Updateの定例更新日を「第2火曜日」に(つまり日本では前日に)お知らせする方法として、「明日は毎月恒例のWindows Updateの日(第2火曜日の翌日)」というメッセージを表示させるタスクを紹介しました。このタスクは毎月第2火曜日の9:00に実行するようにスケジューリングしていたのですが、当時はWindows 10 バージョン1809だったので上記の要件は満たさず、問題なく機能しているようでした(画面1)。

画面1
画面1 毎月第2火曜日に翌日の定例のWindows Updateをお知らせするタスク。Windows 10 バージョン1809だった当時は問題なく機能した

 その後、Windows 10 バージョン1903にアップグレードしましたが、その時点で上記の要件を満たしてしまうことになります。しかし、第2火曜日の9:00にちゃんとメッセージを表示していたように記憶しています。記憶は定かではありません。これは一体どういうことでしょうか。このバグの影響を受けるはずの「Windows 8.1」「Windows Server 2016」、Windows 10 バージョン1903の3台にダミーのタスクを作成して実験してみました。

バグ再現テストを仕込む

 Windows 10 バージョン1903(画面2)、Windows 8.1(画面3)、Windows Server 2016の3台に、次のような設定で、毎週の金曜日と月曜日に「プログラムの開始」操作でログファイルを出力するだけの簡単な2つのタスクを作成しました。「次回の実行時刻」を見る限り、それぞれ次の金曜日と月曜日のAM9:00(JST)に実行が予定されているのが分かります。

DemoFridayTask

 トリガー:毎週金曜日、AM9:00に起動

 操作:powershell.exe -Command "& {(Get-Date).ToString('yyyy/MM/dd dddd HH:mm') >> C:\work\logs\FridayTask.log}"


DemoMondayTask

 トリガー:毎週月曜日、AM9:00に起動

 操作:powershell.exe -Command "& {(Get-Date).ToString('yyyy/MM/dd dddd HH:mm') >> C:\work\logs\MondayTask.log}"


画面2
画面2 Windows 10 バージョン1903のPCに、毎週金曜日と月曜日のAM9:00(JST)に開始し、ログファイルに日時を書き込むタスクを別々に作成
画面3
画面3 Windows 8.1のPCに、毎週金曜日と月曜日のAM9:00(JST)に開始し、ログファイルに日時を書き込むタスクを別々に作成

 この例では「曜日」を含めるため、Windows PowerShellの「Get-Date」コマンドレットを利用していますが、日時だけを出力するなら「cmd.exe /c "echo %DATE%%TIME% >> C:\Work\logs\ファイル名.log"」のように簡単に記述できます。

 タスクが正常に実行されれば、「C:\Work\Logs\FridaryTask.log」と「MondayTask.log」には次のように「年月日 金曜日 09:00」および「年月日 月曜日 09:00」のテキストが記録されるはずです。謎のバグが再現するなら、それぞれ「年月日 木曜日 09:00」および「年月日 日曜日 09:00」になるでしょう。

C:\Work\Logs\FridayTask.log

 2019/08/23 金曜日 09:00

 2019/08/30 金曜日 09:00

 ...


C:\Work\Logs\MondayTask.log

 2019/08/26 月曜日 09:00

 2019/09/02 月曜日 09:00

 ...


前日に実行されるではなく、前日と当日の2回だった

 さて、1週間後の結果を見てみましょう。確かにWindows 10 バージョン1903、Windows 8.1、Windows Server 2016の全てにおいて、タスクは指定した曜日の前日のAM9:00(JST)に正しく実行されていました。それだけでなく、指定した曜日当日のAM9:00(JST)にも再び実行されていました(画面4)。

画面4
画面4 曜日指定のタスクが前日にも実行されるという謎現象の再現を確認。画面はWindows 10 バージョン1903、Windows 8.1とWindows Server 2016も同様

 Japan Windows Commercial Supportフォーラムに公開された情報を見るだけでは、曜日指定のAM9:00(JST)のスケジュールの曜日判定が、前の曜日に誤って解釈され、当日ではなく前日前に実行されるのではと読み取りました。しかし、当日の本来のスケジュールはちゃんと機能して、それ以外に余計な実行が増える(1週間に+1回)ということでした。

 公開情報にある回避策のように、AM9:00(JST)ちょうどではない前後に開始時刻をずらせば、前の曜日に余計に実行されることがないことを確認しました。筆者は毎週日曜日のAM8:59:59(JST)、AM9:00:00(JST)、AM9:00:01(JST)、AM9:01:00(JST)で試しましたが、バグが発現したのはAM9:00:00(JST)だけでした(画面5)。公開情報のそれ以外を信じるなら、Windows 10 バージョン1703〜1809ではこのバグは存在しません(実際に確認したわけではありません)。

画面5
画面5 曜日指定で前日に実行されるのは、AM9:00:00(JST)の場合のみ。1秒前後ずらせば前日に実行されることはなかった

 今回のバグもおよそ信じ難いものでした。しかも、「Windows 10の更新履歴」(https://support.microsoft.com/ja-jp/help/4498140/)や「Windows リリース正常性ダッシュボード」(https://docs.microsoft.com/en-us/windows/release-information/status-windows-10-1903、英語のみ)には既知の問題(Known issues)として公開されていません。タスクスケジューラには、まだまだ想定外のバグが含まれているかもしれません。そして、それは特定の条件下で突然、発現することになります。

 ユーザーにとっては、それがバグとは簡単に判断できないでしょう。特に「曜日」が絡むと、Microsoftの中の人(開発担当者)も苦手なようです。なお、Windows 10 バージョン1903でしか確認していませんが、2019年9月の定例の品質更新プログラムでは、この問題は依然として解消していません(金曜9:00にスケジュールされたタスクが9月のWindows Updateの翌日の9月12日9:00に実行されました)。

 スケジュールされたタスクを用いて、何らかの処理を自動実行させたい場合は、今回紹介したようにダミーのタスクを登録して、ログオンの有無や最上位権限での実行などを含め、その他の項目とともに期待通りの日時にタスクが実行されているかどうかを確認することをお勧めします。

 前回、そして今回のバグの存在を考えると、タスクを実行するユーザーのアクセス許可や操作内容よりも、指定した日時に確かに実行されることを確認することが重要だと思います。しかし、今回のバグのように、更新プログラムでテストが台無しにされることがあるので、自動実行タスクの実行状態の日々の監視も欠かせません。

 また、今回のテスト中、指定した開始時刻や全く関係のない日時の実行履歴として「オペレーターまたは管理者が要求を拒否しました。(0x80010E0)」のエラーを目にすることもありました。

 シビアな要件(例えば、業務システムの月次集計バッチの開始、製造機械設備の制御など)がある場合は、信頼のおけないタスクスケジューラに頼るのは破壊的な結果を招くかもしれません。信頼できる他社のジョブ管理ツールの導入を検討した方がよいでしょう。

おまけ──「タイムゾーン間の同期」って何?

 ところで、タスク開始時刻の設定の横にある「タイムゾーン間の同期」オプションの使い方はご存じでしょうか。英語のUI(ユーザーインタフェース)では「Synchronize across time zones」です。「Windows 7」の場合は、「タイムゾーンにまたがる同期」です。

 よくある誤解の1つが、このオプションをオンにすると、協定世界時(UTC)で時刻を指定したことになる、つまり「9:00、タイムゾーン間の同期:オン」にすると、UTCの9:00にタスクが実行されるという誤解です。結論から言うと、日本国内で(日本標準時《JST》のタイムゾーンで)PCを使用している限り、「タイムゾーン間の同期」がオンでもオフでも開始時刻に影響は全くありません。

 「タイムゾーン間の同期:オフ」で日時を設定すると、ローカル時刻に従ってタスクが実行されます。タイムゾーンが変更されれば、変更されたタイムゾーンのローカル時刻に従います。

 これに対して、「タイムゾーン間の同期:オン」で日時を設定すると、設定時のローカル時刻がUTCを基準とした絶対時刻に変換されて開始時刻として保存されます(表示はローカル時刻のままです)。そのため、タイムゾーンが変更されたとしても、タスクが実行される絶対時刻には影響されません。ローカル時刻としての開始時刻はタイムゾーンが変更される前とは異なることになります。

 これは、「Get-ScheduledTask」コマンドレットで開始時刻(StartBoundary)を参照してみると、よく分かります(画面6画面7)。

画面6
画面6 DemoFridayTaskは「タイムゾーン間の同期:オフ」で9:00開始、DemoDailyTaskは「タイムゾーンの同期:オン」で12:00開始の場合のWindows 8.1のGet-ScheduledTaskコマンドレット実行結果。DemoDailyTaskはタイムゾーンの変更(tzutil)の影響を受けない
画面7
画面7 DemoDailyTaskは「タイムゾーン間の同期:オフ」で12:00開始、DemoDailyTaskZは「タイムゾーン間の同期:オン」で12:00開始の場合のWindows 10のGet-ScheduledTaskコマンドレット実行結果。Windows 8.1とStartBoundaryの形式は異なるが、タイムゾーンを変更してもDemoDailyTaskZの開始時刻はUTCに対して固定

 例えば、日本標準時(JST)で「12:00開始、タイムゾーンの同期:オン」を設定した場合、タスクの開始時刻は「UTC 03:00」として保存され、その開始時刻はタイムゾーンの変更の影響を受けません。Windows 8.1の場合は「03:00:00Z」のように最後に「Z」が付いて保存され、Windows 10の場合は開始時刻+設定時のUTCとの差異「12:00:00+09:00」で保存されます

 「タイムゾーン間の同期」は、サマータイムによる時刻の変動の影響や、タイムゾーンの変更の影響を受ける可能性がある場合、タスクの作成者がローカル時刻と絶対時刻のどちらで実行するかの選択肢を提供するものだと思います。オンにするかオフにするかは、タスク作成者の判断です。

 ちなみに、「Windows XP」の「タスク」にはこのオプションが存在せず、タスクがスキップされたり、重複して実行されたり、タスクの実行順序が変わったりしないように、Windowsが自動調整してくれていたようです(その仕様に関する技術情報「KB325413」は既に削除されてしまいました)。また、Windows XPのころは、世界中を渡り歩くPC(タイムゾーンがしょっちゅう変更されるPC)なんて想定されていなかったことでしょう。

 「タイムゾーン間の同期」についての公開情報が乏しく、Windows XPのときの仕様が現在のWindowsにも存在するのかどうかも分かりません(タスクスケジューラの公式ドキュメントhttps://docs.microsoft.com/ja-jp/windows/win32/taskschd/task-scheduler-start-pageには見当たりません)。筆者はサマータイムが導入されていない日本でしかPCを使用しませんし、クラウド上のインスタンスは全て日本標準時で設定しています。PCを持って海外に渡航する予定もありません。ですので、このオプションについてこれ以上は踏み込みません。

 もし、日本でサマータイムが導入されたとしたら、あるいはサマータイムの影響下にある環境でPCを使用することになったとしたら、そのときに考えて、必要であればテストしてみるでしょう。しかし、おそらく切り替え時期のタスクのスケジュールを可能な限り避けると思います。サマータイムの時刻のシフトは、想定外のバグが発現しそうなところだからです。

 欧米はサマータイム導入からの歴史が長く、タスクのスケジューリングの実績やノウハウは豊富と考える人もいるかもしれませんが、曜日との付き合いは、それよりもはるかに長いのですから。

筆者紹介

山市 良(やまいち りょう)

岩手県花巻市在住。Microsoft MVP:Cloud and Datacenter Management(2019-2020)。SIer、IT出版社、中堅企業のシステム管理者を経て、フリーのテクニカルライターに。Microsoft製品、テクノロジーを中心に、IT雑誌、Webサイトへの記事の寄稿、ドキュメント作成、事例取材などを手掛ける。個人ブログは『山市良のえぬなんとかわーるど』。近著は『ITプロフェッショナル向けWindowsトラブル解決 コマンド&テクニック集』(日経BP社)。


Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る