
スケジュールされた時間にBash機能を実行したいです。正しいツールはat
コマンドだと思います。
しかし、うまくいかないようです。
function stupid () {
date
}
export -f stupid
cat << EOM | at now + 1 minute
stupid
EOM
しばらく待ってからメールを確認しましたが、次のエラーが表示されました。
sh: line 41: syntax error near unexpected token `=\(\)\ {\ \ date"
"}'
sh: line 41: `"}; export BASH_FUNC_stupid()'
特に関数が機能していることを知っているので、ここで何が間違っているのかわかりません。
$ stupid
Fri May 29 21:05:38 UTC 2015
エラーを見ると、関数の実行に間違ったシェルが使用されているようですが(sh
代わりにbash
)、確認してみると を指すように$SHELL
見え、/bin/bash
マニュアルページに次のようにat
示されています。
$ echo $SHELL
/bin/bash
$ man at
...
SHELL The value of the SHELL environment variable at the time
of at invocation will determine which shell is used to
execute the at job commands.
したがって、Bashは私の機能を実行するシェルでなければなりません。
どうなりますか?私のBash機能を一緒に実行する方法はありますかat
?
答え1
Bash機能は環境を介してエクスポートされます。このat
コマンドは、環境を再現するシェルコードを生成し、呼び出しプロセスの環境、umask、および現在のディレクトリをスクリプトで使用できるようにします。 at ジョブで実行されるスクリプトは次のとおりです。
#!/bin/bash
umask 022
cd /home/nick
PATH=/usr/local/bin:/usr/bin:/bin; export PATH
HOME=/home/nick; export HOME
…
stupid
()
以前のバージョンのbashでは、関数名と関数を定義したコードで始まり、設定された値を含む変数に関数をエクスポートしました。
stupid="() {
date
}"; export stupid
これにより、多くのシナリオがセキュリティの脆弱性に対して脆弱になります。シェルショックバグ(で見つかりましたスティーブン・チャジェラス)を使用すると、誰でも任意の名前で環境変数の内容を注入して、bashスクリプトから任意のコードを実行できます。 Shellshockの修正を含むbashバージョンは異なるアプローチを使用します。名前に環境変数で見つからない文字を含む変数に関数定義を格納し、シェルはそれを割り当てとして解析しません。
BASH_FUNC_stupid%%="() {
date
}"; export stupid
これは有効な sh 構文ではないため、%
bash でも at 操作は関数を使用するかどうかに関係なく失敗します。これat の Debian バージョンは多くのLinuxディストリビューションで使用されています。変更バージョン3.16では、シェルスクリプトに有効な名前を持つ変数のみがエクスポートされます。したがって、atの最新バージョンはShellshockの後ろからbashを介して機能をエクスポートしませんが、古いバージョンは失敗します。
Shellshock 以前のバージョンの bash を使用しても、エクスポートされた機能は、at ジョブ自体ではなく at ジョブで開始された bash スクリプト内でのみ機能します。 atジョブ自体内では、bashによって実行されてもstupid
bashは起動時にのみ機能を取得する別の環境変数です。
関数をatジョブとしてエクスポートするには(bashまたはバージョンに関係なく)、その関数をファイルに入れ、ジョブからファイルを取得するか、ジョブに直接含めます。定義されたすべての関数を読み取り可能な形式で印刷するには、を使用しますdeclare -f
。
{ declare -f; cat << EOM; } | at now + 1 minute
stupid
EOM
答え2
at
/bin/sh
代わりに使用するように設計されているため、/bin/bash
使用可能なコード序文が前に追加されます。何かを接続して使用するには、次の簡単な機能を使用してください。at -c {jobnumber}
bash
at_with_bash_alias_and_functions(){
(
echo "exec /bin/bash <<END"
alias
typeset -f
cat
echo END
) | sed 's/\$/\\$/g' | at "$@"
}
エイリアスと関数が存在するかどうかを表示します。
at_with_bash_alias_and_functions now <<< "alias;typeset -f"
制限事項:インライン処理はシェル置換のため、構文が失われる可能性があり、構文を検証する代わりに.usesat
のように動作します。exec cat
exec bash
答え3
まあ、あなたはすでに郵便を受け取ることになることを知っています。クールだから君は絶対にできるbash
メールが届いたときに実行される関数です。
ソースman bash
:
$MAILPATH
メールを確認するファイル名をコロンで区切ったリストです。メッセージが特定のファイルに到着したときに印刷されるメッセージは、ファイル名とメッセージを区切る区切り文字を使用して指定できます。?。メッセージテキストに使用されている場合は、
$_
現在のメールファイルの名前に展開されます。例:MAILPATH='/var/mail/bfox?"You have mail":~/shell-mail?"$_ has mail!"'
bash
この変数にはデフォルト値が指定されていますが、使用されるユーザーメールファイルの場所はシステムによって異なります。(たとえば、/var/mail/$USER
)。
ところで、$_
いいえただこの文脈では、可能な拡張 - コマンドの置換を含め、ほぼすべてを拡張できます。実は必ずしも必要はありませんが印刷何もない。ファイルに必ずしも以下を含める必要はありません。郵便$MAILCHECK
または - シェルは、1 秒あたりの確認結果ファイルが最後に表示されてから変更されたことを示すときに通知しようとします。
それにもかかわらず、シェルがこれを処理する方法は$MAILxxxx
通常、プロンプトによって異なります。つまり、$MAILCHECK
値に関係なくタイムリーに新しいプロンプトを取得しないと、通知が表示されません。次のプロンプトを通知するためにトリガーするまで通知を受け取ります。これはよくわかりませんが、set -b
影響を与える可能性があります。
とにかく、このようなことをする方法はいくつかあります。おそらく最も確実な方法は、信号を使用してタスクat
をスケジュールすることです。たとえば、次のようになります。
echo kill -USR1 "$$" | at now + 1 minute
trap some_func USR1
何が起こっているのか確認してください。