atコマンドで指定時間にJobを単発実行させる
はじめに
最近、CrontabみたいなJobを定期的にスケジュールするのでは無くて、指定時間に単発で実行したいみたいな要件にぶち当たって、ちょっと調べていたらUnix系のOSにat
というコマンドがあることに気がついたので機能を試して見ようかと思います。
at コマンドとは
標準出力、もしくはファイルからコマンドを受け取って、/bin/sh
を使って指定時間にシェルを起動するコマンドです。Corntabなどは日時の指定のみで、最長一年に一回は実行されるのに対してatコマンドは年の指定まで行なうことが可能で、指定した時間に一回のみといった実行が行えます。
実行時の環境変数(BASH_VERSINFO
、 DISPLAY
、 EUID
, GROUPS
、 SHELLOPTS
、 TERM
、 UID
以外)、ワークディレクトリ、umaskなどはコマンド実行時の状態でキープされます。
また、at
はsetuid
プログラムで、LD_LIBRARY_PATH
やLD_PRELOAD
などの環境変数も読み込まれないようです。
使ってみる
環境
コマンドの実行環境は以下の通り、
$ uname -srvmpio Linux 5.4.0-62-generic #70-Ubuntu SMP Tue Jan 12 12:45:47 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a LSB Version: core-11.1.0ubuntu2-noarch:security-11.1.0ubuntu2-noarch Distributor ID: Ubuntu Description: Ubuntu 20.04.1 LTS Release: 20.04 Codename: focal
基本的な操作方法
プロンプトでコマンドを設定する。
atは以下のような形式で、実行できます。
$ at 07:55 01/31/21 warning: commands will be executed using /bin/sh at>
実行すると、>at
という表示が現れプロンプトが起動します。
ここにコマンドを打ち込んでctrl+d
を押すと設定が完了です。
$ at 10:46 01/22/21 warning: commands will be executed using /bin/sh at> java --version > test.txt at> <EOT> job 6 at Fri Jan 22 10:46:00 2021
実施時間をすぎると以下のようにテキストが出力されているのが確認できます。
$ cat test.txt openjdk 15.0.1 2020-10-20 OpenJDK Runtime Environment AdoptOpenJDK (build 15.0.1+9) Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.23.0, JRE 15 Linux amd64-64-Bit Compressed References 20201022_81 (JIT enabled, AOT enabled) OpenJ9 - 0394ef754 OMR - 582366ae5 JCL - ad583de3b5 based on jdk-15.0.1+9)
ファイルを読み込んで実行する
atコマンドはファイルを読み込んで実行することもできます。
まずは、以下のようなシェルスクリプトを用意します。
hello.sh
#!/bin/sh echo "hello, at command" > test.txt
このシェルスクリプトをat
コマンドで実行するには-f
オプションで実行するファイルを指定します。
$ at 21:05 01/22/21 -f hello.sh warning: commands will be executed using /bin/sh job 8 at Fri Jan 22 21:05:00 2021 $ cat test.txt hello, at command
日付の指定の形式について
at
はPOSIX.2 standardを拡張した日付の指定が可能なようです。
HH:MM
- 時間と分を指定できます。この場合、今日の時間にJobが実行され、もしその時間が今日すでに過去である場合は次の日の指定された時間にJobが実行されます。
MMDD[CC]YY
,MM/DD/[CC]YY
,DD.MM.[CC]YY
or[CC]YY-MM-DD
- オプションとして、上記のような形式で年月日を指定することができます。
midnight
、noon
、teatime
- それぞれの時間に実行されます。
today
、tomorrow
- サーフィクスとして上記の表記をつけるとそれぞれ今日と明日を示すことができます。
その他にも結構自由な時間の指定ができるようで、今日から3日後の4pmとかを指定する場合はat 4pm + 3 days
、6月31日の10時AMを指定したい場合はat 10am Jul 31
と行ったような感じで指定することができます。
他にできそうなこと
マニュアルでatコマンドを調べてみると、このコマンドには以下のような、仲間がいるようです。
atq
atrm
- job numberにとって特定されるジョブを削除します。
-r
オプションがエイリアスになっています。
- job numberにとって特定されるジョブを削除します。
batch
- システムのロードアベレージが1.5(かもしくは
atd
コマンドで指定された値)以下になった際にJobを実行する。
- システムのロードアベレージが1.5(かもしくは
他にも-m
使うなどするとジョブの実行時にユーザにメールを送ることができるようです。