atコマンドについていろいろ実験してみたよ | ~magi mode~ver3.10

~magi mode~ver3.10

マジックの練習は辞めて今はパソコンばかりいじっている。
アニメ好きだがオシャレも好き。
二次元と三次元の両立を図る日々。
最近トレーニングにもハマってる。

atコマンドは指定時間にジョブを実行させるコマンドだけど、これを使ってみようとしたらなかなかうまくいかない。
ためしにこんなことをしてみた

$ at 18:00
at> echo "aaa"
at> [EOT]  (ctrl+dでatを抜ける)
$

なぜか表示されない。
次にこうしてみた。

$ echo "aaa" | at now + 1minute

何も起こらなかった。
/etc/cron.d/cron.allowにユーザ名書いてないのが原因かと思って書いたけど変わらない。
調べたら標準出力が原因かもしれないとわかったので端末もう一個開いてttyでデバイスを調べる。

$ tty
/dev/pts/3

現在使用中の端末は/dev/pts/3だと判ったのでそれを指定してみる。

$ echo "aaa" > /dev/pts/3 | at now + 1minute

するとechoが成功した。
が、なぜか1分後ではなくすぐに実行されてしまった。
しかしatqでatの予定を見ると「1分後に実行します」との意味の文章が表示されている。
つまりまだジョブは実行してないよってことだ。
うーん…。
以下のようにすると正常に1分後に実行された。

$ echo 'echo "aaa" > /dev/pts/3' | at now + 1minutes

なぜechoをechoすると正常に指定時間に実行されるのだろう?
その後いろいろ試してみた。


1.「echo "test" > /dev/pts/3」と書いたシェルスクリプトを実行させる。

$ at -f ./test.sh now + 1minute

うまく1分後にechoできた。
だが同じ意味合いと思っていた以下のコマンドを実行させたときは1分後ではなく先と同じように即座にechoが実行されてしまった。

$ ./test.sh | at now + 1minute

2.「echo "test"」のみ書いたシェルスクリプトの実行結果を/dev/pts/3に出力させる

$ at -f ./test.sh now + 1minute > /dev/pts/3

何も表示されなかった。

3.at登録画面からechoしてみる。

$ at now + 1minute
at> echo "test" > /dev/pts/3
at> [EOT]

正常に1分後にechoされた。

結論
パイプを使ってatする場合は一応ジョブの実行時刻設定はされるが、実際にジョブが実行されるのは入力した直後のようだ。つまりatではパイプは使わない。
しかし先の「$ echo 'echo "aaa" > /dev/pts/3' | at now + 1minutes」のようにすればよくわからんけど正常に指定時刻にechoが実行される。
シンプルにしたければパイプは使わない方が良いというところか。
結論を言うと、例えばechoを使う場合ならば上記実験の3のように

$ at now + 1minute

等でat登録画面から設定した方が良さそうだ。
また、echoならば出力デバイスを指定しておくこと。



p.s.

$ echo "aaa" > /dev/pts/3 | at now + 1minute



$ echo 'echo "aaa" > /dev/pts/3' | at now + 1minutes

の違いがわかったかも。
1つ目の方はパイプを使ったことによって「echo "aaa"」の実行結果を1分後に実行しようとしているのだ。
つまりatは1分後に「aaa」を実行しようとしてしまうため失敗する。
対して2つ目の方は「echo 'echo "aaa"'」の実行結果を1分後に実行しようとするわけだ。
つまりatは1分後に「echo "aaa"」を実行するわけだ。
こういうことだったのか…。
リダイレクトとパイプの勉強不足というか冷静に考えればわかることなのにね。