ShebangがcronにSHELLを設定しない

ShebangがcronにSHELLを設定しない

以下を含むスクリプトがあります。

#!/bin/bash
printenv

コマンドラインから実行するとき:

env testscript.sh
bash testscript.sh
sh testscript.sh

毎回出力しますSHELL=/bin/bashが、cronで実行すると常に出力されますSHELL=/bin/sh。 cronにshebangを適用させるにはどうすればよいですか?

クローンパスを確認しましたが、これには/ binが含まれています。

答え1

shebangが動作しており、cronはそれとは何の関係もありません。ファイルの実行時にファイルの内容がで始まると、#!カーネルは#!その行で指定されたファイルを実行し、元のファイルを引数として渡します。

SHELL問題は、スクリプトが実行されているシェルがシェルスクリプトに反映されていると信じているようです。そうではありません。実際、ほとんどの場合、SHELLユーザーの好みを意味します。インタラクティブシェルの役割は、ターミナルエミュレータなどのアプリケーションに実行するシェルを決定させることです。 cronでSHELLcrontabエントリ(時間表示の後の行の一部)を実行するために使用するプログラムをcronに通知する変数。

シェルはSHELL起動時に設定されない限り、この変数を設定しません。

事実はSHELLおそらく/bin/sh関係がないでしょう。スクリプトには#!/bin/bash1行があるため、bashによって実行されます。自信がある場合は、ps $$スクリプトを追加してpsスクリプトを実行しているシェルに関する情報を表示してください。

答え2

バッシュリファレンスマニュアル説明する:

SHELL - シェルの絶対パス名がこの環境変数に保持されます。シェルがシェルなしで起動されると、Bashはそのシェルに現在のユーザーログインシェルのフルパス名を割り当てます。

man 5 crontab説明する:

いくつかの環境変数はcron(8)デーモンによって自動的に設定されます。 SHELL は /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

Sherbonが動作します。あなたの行動が記録されます:)

答え3

ただし、cronで実行すると常にSHELL = / bin / shが出力されます。なぜこれですか?

これはcronSHELLがに設定されているためです/bin/sh。これは、cron が crontab エントリの実行に使用する基本プログラムであるためです。からman 5 crontab

いくつかの環境変数はcron(8)デーモンによって自動的に設定されます。 SHELLは/bin/shに設定されています...

Evgeny Vereshchaginの答えがすでに指摘したように、変数がすでに設定されている場合、Bashは後でそれを修正しません。

cronにshebangを適用させるにはどうすればよいですか?

クローンはすでに適用中です。あなたのスクリプトのために、次の例に示すように。

以下があるとしましょう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

答え4

shebangを次に変更します。

#!/bin/env bash

または、crontab -ecronの独自の環境変数が異なるため、独自の環境変数を使用してスクリプトを実行するように実行します。


ちなみに、によるとこの記事はaskubuntuにあります。cron、スクリプトの上部にPATHを提供する必要があります。

PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# rest of script follows

ただし、PATHに正しい検索ディレクトリがあると思われる場合は、それを除外できます。

関連情報