以下を含むスクリプトがあります。
#!/bin/bash
printenv
コマンドラインから実行すると:
env testscript.sh
bash testscript.sh
sh testscript.sh
毎回Shell=/bin/bash
を出力します。ただし、cronから実行すると、常にShell=/bin/sh
が出力されます。どうしてこれなの?どうすればcronにシバンを適用させることができますか?
私はすでにcronPATHをチェックしました。/binが含まれています。
Shebangは機能しており、cronはそれとは何の関係もありません。ファイルが実行されるとき、そのファイルの内容が#!
で始まる場合、カーネルは#!
行で指定されたファイルを実行し、元のファイルを引数として渡します。
あなたの問題は、シェルスクリプトのShell
がスクリプトを実行しているシェルを反映していると信じているように見えることです。これはそうではありません。実際、ほとんどのコンテキストで、Shell
はユーザーが好むインタラクティブシェルを意味し、ターミナルエミュレータなどのアプリケーションが実行するシェルを決定することを目的としています。 cronでは、Shell
は、crontabエントリ(時刻表示の後の行の部分)を実行するために使用するプログラムをcronに指示する変数です。
シェルは、開始時に設定されていない限り、Shell
変数を設定しません。
Shell
が/bin/sh
であるという事実はおそらく無関係です。スクリプトには#!/bin/bash
行があるため、bashによって実行されます。自分を納得させたい場合は、スクリプトにps $$
を追加して、ps
にスクリプトを実行しているシェルに関する情報を表示させます。
Bashリファレンスマニュアル 言います:
シェル-シェルへのフルパス名は、この環境変数に保持されます。シェルの起動時に設定されていない場合、Bashは現在のユーザーのログインシェルのフルパス名を割り当てます。
man 5 crontab
言います:
いくつかの環境変数は、cron(8)デーモンによって自動的に設定されます。シェルは/ bin/shに設定され、LOGNAMEとHOMEはcrontabの所有者の/ etc/passwd行から設定されます。 PATHは "/ usr/bin:/ bin"に設定されています。 HOME、Shell、PATHは、crontabの設定によって上書きされる場合があります
したがって、Shell
変数はBashの開始時に設定されます。
Shell=/bin/awesome/Shell bash testcript.sh
をお試しください。 Shell=/bin/awesome/Shell
が表示されます
シバンは動作します。文書化された動作があります:)
ただし、cronから実行すると、常にShell =/bin/shが出力されます。どうしてこれなの?
これは、cronがShell
を/bin/sh
に設定したためです。これは、cronがcrontabエントリを実行するために使用するデフォルトのプログラムであるためです。 man 5 crontab
から:
いくつかの環境変数は、cron(8)デーモンによって自動的に設定されます。シェルは/ bin/shに設定されています...
そして、Evgeny Vereshchaginの回答ですでに示されているように、その変数は、すでに設定されている場合、後でBashによって変更されることはありません。
どうすればcronにシバンを適用させることができますか?
次の例からわかるように、Cronはすでにそれを適用しています独自のスクリプト用。
次のdisplay_process_tree.sh
があるとします。
#!/bin/bash
pid=$$
depth=0
while
[ "$pid" -gt 0 ] &&
read -r ppid name < <(ps -o ppid= -o comm= -p "$pid")
do
eval $(echo printf '" %0.s"' {0..$depth})
if [[ -r /proc/$pid/exe ]]; then
echo -n "$name - "
readlink -f /proc/$pid/exe
else
echo $name
fi
pid=$ppid
depth=$((depth+1))
done
そして、このようなcrontab:
* * * * * /path/to/display_process_tree.sh > /tmp/display_process_tree.log
ここで、出力が/tmp/display_process_tree.log
に到着するのを待つと、次のようなプロセスツリーが見つかります。
display_process - /bin/bash
sh - /bin/dash
cron
cron
systemd
これは、cronが実際に/bin/sh
(私のシステムでは/bin/dash
にリンクされている)を使用して、スクリプトの新しい/bin/bash
プロセスを開いたことを示しています。