なぜこの「at」コマンドが標準出力に出力されないのですか?


15

私は比較的Linux初心者です。を使用atせずに後で開始するタスクをスケジュールできるように、使用方法を学習しようとしていsleepます。私は助けのためにこの前の質問を見てきました。

私の質問は、私が作成した次のサンプルbashスクリプトでは、「実行中」が標準出力(つまり、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、標準出力とどのように違いますか?


これを試してくださいsleep 3m; echo Running
。– Jasen

回答:


18

atログインしているユーザーセッションのコンテキストでコマンドを実行しないためです。これは、コマンドを任意の時間に実行するようにスケジュールしてからログアウトすると、システムが指定された時間にコマンドを実行できるようにするという考え方です。

のマニュアルページには、at(1)特に述べられていることに注意してください(私の強調):

ユーザーには、コマンドからの標準エラーと標準出力(ある場合)が郵送されます。メールは/ usr / sbin / sendmailコマンドを使用して送信されます。

したがって、ローカルのメールスプールを確認するか、失敗するとローカルシステムのメールログを確認する必要があります。/ var / spool / mail / $ USERは、おそらく開始するのに適した場所です。

また、「開始」と「終了」は外側のスクリプトに由来し、それ自体はまったく関係ないことに注意してくださいat。それらまたはat呼び出しを取り出すと、基本的に同じ結果が得られます。


8

@MichaelKjörlingが説明したように、atジョブによって生成される出力はすべてキャプチャされ、電子メールで送信されます。実行中のMTA-Mail Transfer Agentがボックスにない場合、電子メールはあいまいである可能性があり、atこれを試みていることさえわかりません。

A MTAは、このようなプログラムであるsendmail、または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

メールキューの「受信トレイ」にこれがあります。

     muttの受信トレイのss

このメールをチェックしてみましょう。

     muttのメッセージのss

そしてそれは働いた。


@MichaelKjörling-mutt rulz 8
slm

5

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>

1分後、「ZZZZZ」が端末に表示されます...


2

上記の答えは、それを行うための標準的/「正しい」方法です。

より「エンドユーザー」の観点からより簡単な別のアプローチは、スケジュールされたタスクまたはバックグラウンドタスクで出力を「ログ」ファイルに書き込むことです。ファイルはシステム上のどこにあってもかまいませんが、タスクがrootとして(from 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

テキストエディターで両方のスクリプトを作成し、保存してから、を使用して各実行可能ファイルを作成しました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ために使用しました>。アプリケーションに最適な方を使用してください。


ATコマンドを使用してログファイルに出力を書き込む例を提供できますか、私は次の方法で試していますが、結果はありません、現在+ 1分で> echo "" hello ">> / home / camsarch / cams_scripts / texsttest。 txt at> <EOT>
Pavan Kumar Varma

@PavanKumarVarma- atファイルへの書き込みに使用する単純な(テスト済みの)サンプルを追加しました。この例では、呼び出しシーケンスが逆になっているように見えます。私はatいつジョブを実行するかを伝えるのがあまり得意ではないので、近い将来に時間をハードコーディングしました。
ジョー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.