私はLinuxにとって比較的初心者です。at
を使用せずに後で作業を開始するようにスケジュールできるように使用方法を学びたいsleep
。前の質問助けを求める。
私の質問は私が作った次の例のbashスクリプトでなぜ「走る」私が知っている限り、stdout(bashコンソールなど)で印刷することはできません。
#!/bin/bash
echo "Started"
at now + 1 minutes <<EOF
echo "Running"
EOF
echo "Finished"
私が見る唯一の出力は、例えば次のとおりです。
Started warning: commands will be executed using /bin/sh job 3 at Fri Jul 12 17:31:00 2013 Finished
私の質問に対する答えは警告で見つけることができますか?それでは、/bin/sh
標準出力とどう違いますか?
答え1
at
これは、ログインしたユーザーセッションのコンテキストではコマンドが実行されないためです。アイデアは、いつでもコマンドを実行するようにスケジュールし、ログアウトすると、システムが指定された時間にコマンドの実行を処理することです。
マニュアルページには次のように具体的at(1)
に明示されています(私の強調)。
ユーザーにメールが送信されます。コマンドの標準エラーと標準出力(使用可能な場合)のメールは、/usr/sbin/sendmailコマンドを使用して送信されます。
したがって、ローカルメールプールを確認し、失敗した場合はローカルシステムメールログを確認する必要があります。 /var/spool/mail/$USERは始めるのに最適な場所かもしれません。
at
さらに、「開始」と「完了」は外部スクリプトから派生し、それ自体はまったく関係がありません。取り出したりat
電話したりすると、本質的に同じ結果が得られます。
答え2
私はDebian 8.1を実行しています(jessie)。
ttyを使用して、「at」出力を端末にインポートできます。
$ tty
/dev/pts/1
$ at now + 1 min
warning: commands will be executed using /bin/sh
at> echo 'ZZZZZ' > /dev/pts/1
at> <EOT>
しばらくすると、端末に「ZZZZZ」が表示されます。
答え3
@MichaelKjörlingが説明するように、あなたの仕事で作成されたすべての結果はat
キャプチャされ、あなたに電子メールで送信されます。走っていない場合MTA - メール転送エージェントat
電子メールがメールボックスに表示されると、電子メールが輻輳して電子メールがこの操作を試みているという事実さえ知らない可能性があります。
sendmail
MTAは、またはpostfix
電子メールを適切な宛先に「ルーティング」することができるプログラムです。この場合、/var/spool/mail
ローカルシステムのメールキュー(ディレクトリの下のファイル)に転送されます。システムの各ユーザーは、このディレクトリにキューを持つことができます。
私のFedoraシステムから起動すると、sendmail
ローカルメール配信が届きます。しかし、私は通常消えています。
$ sudo service start sendmail
これで、自分のユーザーアカウントのメールキューが空であることを確認できますsaml
。
$ ll /var/spool/mail/|grep saml
-rw-rw----. 1 saml mail 0 Jul 12 19:33 saml
これでジョブを実行しますat
。
$ at now + 1 minutes <<EOF
echo "Running"
EOF
job 96 at Fri Jul 12 19:38:00 2013
ジョブが実行を待っていることがわかりますatq
。
$ atq
96 Fri Jul 12 19:38:00 2013 a saml
数分後に再実行すると、タスクがat
完了したことを確認できます。
$ atq
$
ところで、MTA が実行されていると、端末に次のメッセージが表示されます。
/var/spool/mail/saml に新しいメールがあります。
それでは、確認してみましょう。
$ ll /var/spool/mail/|grep saml
-rw-rw----. 1 saml mail 651 Jul 12 19:38 saml
はい、メールが届きました。次のコマンドを使用して確認しますmutt
。
$ mutt -f /var/spool/mail/saml
メールキューの「受信トレイ」には次のものがあります。
このメールを見てみましょう。
効果がありました。
答え4
上記の答えは標準/「正しい」方法です。
より「エンドユーザー」の観点から見ると、もう1つの簡単なアプローチは、スケジュールされたジョブまたはバックグラウンドジョブがその出力を「ログ」ファイルに書き込むことです。このファイルはシステムのどこにでも配置できますが、ジョブがルート(スレーブなどcron
)で実行されている場合は、次のいずれかの場所に/var/log
ファイルを保存することをお勧めします。
私は/var/log/maint
ディレクトリを作成し、誰もが読めるようにしました。 「backup」というディレクトリの下に読み取ることができるファイルがあり、ここでバックアップスクリプトの出力を記録します。
私のファイルがシステム生成コンテンツと混在しないように、独自のディレクトリを作成しました。
そこに物を入れてください(bashに):
BACKUP="/var/log/maint/backup"
echo "my message" >> "${BACKUP}"
これにより、>>
メッセージが毎回上書きされるのではなくファイルに追加されます。
出力が多いスクリプトがある場合は、出力にスクリプトまたは関数を使用してすべての操作が同じ方法で実行されます。私の現在(過度のバージョン)は次のとおりです。 (ターミナルでスクリプトを実行し、デバッグ目的で何が起こっているのかを確認しようとすると、VERBOSEエントリが表示されます。)
#!/bin/bash
## backup_logger
## backup system logging module
## Copyleft 01/20/2013 JPmicrosystems
## Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]
## If present, -v says log to console as well as to the log file
## <caller> is the name of the calling script
## If <caller> <log message text> is not present, write a blank line to the log
## Must be placed in path, like ~/bin
## If log is owned by root or another user, then this must run as root ...
## If not, it just aborts
##source "/home/bigbird/bin/bash_trace" ## debug
SCRIPT_NAME="$(basename $0)"
USAGE="Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]"
SYSLOGDIR='/var/log/maint'
SYSLOGFILE="${SYSLOGDIR}/backup.log"
LOGGING=1
VERBOSE=0
if [ "${1}" == "-v" ]
then
VERBOSE=1
shift
fi
##LOGGING=0 ## debug
##VERBOSE=1 ## debug
## Only zero or two parameters allowed - <caller> <log message text>
RC=0
if [ "$#" -eq 1 ] || [ "$#" -gt 2 ]
then
echo "${USAGE}"
RC=1
else
if [ ! -w "${SYSLOGFILE}" ]
then
touch "${SYSLOGFILE}"
if [ $? -ne 0 ]
then
echo -e "$(date) ${1} ${2}"
echo "${SCRIPT_NAME} Can't write to log file [${SYSLOGFILE}]"
RC=1
exit ${RC}
fi
fi
if [ -n "${1}" ]
then
(( LOGGING )) && echo -e "$(date) ${1} ${2}" >> "${SYSLOGFILE}"
(( VERBOSE )) && echo -e "$(date) ${1} ${2}"
else
(( LOGGING )) && echo "" >> "${SYSLOGFILE}"
(( VERBOSE )) && echo ""
fi
fi
exit $RC
編集:at
ユーザーファイルに書き込む簡単な例
以前はこれを使ったことがなかったので、いくつかの簡単なスクリプトで問題を解決しました。
最初のスクリプトはイベントをスケジュールするために使用されますat
。コマンド自体は端末に直接入力できますが、怠惰です。特に、テスト中にコマンド履歴をなりすますことなくコマンドを複数回実行する必要がある場合は、これがさらに重要です。
#!/bin/bash
## mytest_at_run
## Schedule a script to run in the immediate future
echo "/home/bigbird/bin/mytest_at_script" | at 00:56
2番目のスクリプトは、実行するようにスケジュールされたスクリプトです。
#!/bin/bash
## mytest_at_script
## The script to be run later
echo "$(date) - is when this ran" >> /home/bigbird/log/at.log
テキストエディタで2つのスクリプトを作成して保存し、使用しましたchmod 700 script-file-name
。便宜上、両方のスクリプトを私の$HOME/bin
ディレクトリに配置しましたが、ユーザーがフルアクセス権を持つ任意の場所にいる可能性があります。テスト用に任意のスクリプトを使用します700
が、シングルユーザーシステムでは755
。
/home/bigbird/log
出力が保存されるディレクトリがすでにありますmytest_at_script
。これは、ユーザーがフルアクセス権を持っているどこでも可能です。スクリプトが実行される前に存在することを確認するか、スクリプトが生成されるようにします。
これを実行するには、コマンドの時間が未来であることをat
確認してから端末で実行しました。mytest_at_run
その後、実行されるまで待ってから確認してください$HOME/log/at.log
。
bigbird@sananda:~/bin$ cat ~/log/at.log
Fri Sep 14 00:52:18 EDT 2018 - is when this ran
Fri Sep 14 00:56:00 EDT 2018 - is when this ran
bigbird@sananda:~/bin$
いくつかの注意:
私のユーザーから実行しても、at
私のディレクトリ、私のホームディレクトリなど、私の環境を知らないので、PATH
そうは思いません。私はcron
他の仕事のようにフルパスを使用します。動作させるには、cron
実行するために何も変更する必要はありません。
私は実行するたびに出力を置き換えるのではなく、ログファイルに出力を追加し>>
ました。あなたのアプリケーションに最適なものを使用してください。mytest_at_script
>