web-dev-qa-db-ja.com

cronは、「。bashrc」および「.bash_profile」で定義された変数を無視します

/ etc/crontabファイルで「シェル」変数を定義しました。

[martin@martin ~]$ grep Shell /etc/crontab 
Shell=/usr/local/bin/bash
[martin@martin ~]$ file /usr/local/bin/bash
/usr/local/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 8.0 (800107), stripped
[martin@martin ~]$ 

さらに、/ etc/crontabファイル内のすべてのスクリプトは、ユーザー「martin」の下で起動されます。ただし、/ home/martin/.bash_profile(ログインシェルの場合)および/ home/martin/.bashrc(非ログシェルの場合)には、大文字と小文字が区別されないいくつかの変数が含まれていますcronジョブの一部ですが、SSH経由でマシンにログインする場合、または新しいbashセッションを開く場合に使用されます。なぜcronはこれらの変数を無視するのですか? cronは、ユーザー "martin"の権限で "/ usr/local/bin/bash my-script.sh"を実行するだけではありませんか?

56
Martin

ジョブの実行中のユーザーに対して、スクリプトの先頭またはジョブの先頭で必要なファイルを入手できます。 「ソース」コマンドは組み込みです。これらのファイルを編集して変更を読み込む場合も、同じことを行います。

* * * * * source /home/user/.bash_profile; <command>

または

#!/bin/bash
source /home/user/.bash_profile

<commands>
80
gNU.be

それはインタラクティブなシェルではないからです。一部のターミナルを開いたときにも同じことが起こります。

この質問を見てください: 。bashrcファイルとは何ですか?|スーパーユーザー

そしてこれでも:

。bashrc、.bash_profile、.environmentの違いは何ですか?| Stack Overflow

接続がログインシェル(またはそうでない)、インタラクティブシェル(またはそうでない)、またはその両方であるかどうかに応じて、異なるスクリプトが起動します。

Bashrcを作成する場合は、次の変更を行う必要があります。

Bashが非対話的に起動されると、たとえば、シェルスクリプトを実行するために、環境内で変数BASH_ENVを探し、そこに表示されている場合はその値を展開し、展開された値をファイルの名前として使用して読み取りおよび実行します。 Bashは、次のコマンドが実行されたかのように動作します。

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi 

ただし、PATH変数の値は、ファイル名の検索には使用されません。

上記のように、非インタラクティブシェルが--loginオプション、Bashはログインシェルの起動ファイルからコマンドを読み取って実行しようとします。

ソース: Bashスタートアップファイル| Bashリファレンスマニュアル| gnu.org

26
Dave C

sourceシェルが使用されている場合、shを実行できない場合があります。これは、crontabに次の行を追加することで変更できます。

Shell=/bin/bash
* * * * * source "/root/.bashrc"; <command>

環境を指定することもできます。

BASH_ENV="/root/.bashrc"
* * * * * <command>

または、ローカルの/home/user/.bashrcがユーザーcronジョブの場合は使用できます(例:crontab -e)。

.bash_profileが存在する場合は、.bashrcを置き換えることができます。

クレジット: cronシェル(shをbashに変更)する方法

13
Jonathan

Cronjobからの.bashrcの取得を妨げる可能性のあるその他のことは、対話型シェルを検出するためにこのファイルが行うすべてのチェックです。

たとえば、Ubuntu 18.04では、ユーザーのデフォルトの.bashrcは次のように始まります。

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

ソーシングしてもすぐに終了するため、何の役にも立ちません。

2
Francois Marier

次のように、-lオプションを使用してbashを呼び出すことができます。

* * * * * /bin/bash -l /path/to/script arg1 arg2

-lオプションは、bashをloginシェルにします。したがって、ユーザーの.bash_profileを読み取ります。 .bashrcから明示的に供給されない限り、ユーザーの.bash_profileは読み取られません。これは、非インタラクティブシェルが.bashrcを自動的に読み取らないためです。ただし、.bashrcinteractiveシェルに役立つものを設定するためのものなので、cronジョブに.bashrcは必要ありません。

バリエーション:

BashがPATH上にある場合、絶対パスを指定する必要はありません。

* * * * * bash -l /path/to/script arg1 arg2

最適化は、execを使用して現在のシェルを置き換えることです。

* * * * * exec bash -l /path/to/script arg1 arg2
2
Robin A. Meade

bashは、それがShellでも、通常のプログラミング言語Perlpythonのように)でも、動作が異なります。

設計上、~/.bash_profile~/.bashrcなどの設定は、ユーザーがbashを再生するときに設定するものですシェルの役割(ログインシェル、インタラクティブシェル)。 xterm(対話型シェル)、sshセッション(ログインシェル)、またはコンソール(ログインシェル)の環境について考えてみましょう。

一方、bashも強力なプログラミング言語systemdでサービスを管理するための多くのスクリプトについて考えてください。これには異なるスタイルの作業が必要です。たとえば、開発者がシステムスクリプトまたはbashプログラムを作成している場合、ユーザーの~/.bash_profileを自動的に取得したくありません。シェルではなく、通常のプログラムです。通常のプログラム(bashプログラムを含む)は当然、現在の作業中の廃止(シェル)からinherit設定になりますが、setではありません。

cronbashのプログラムを作成すると、たまたまbashで作成されます。実際、pythonまたはPerlまたはその他のプログラミング言語で書き込むことができます。次に、bash~/.bash_profileをソースにするオプションを使用できます(読み取り:設定ユーザーのシェル、それはたまたまあなたのプログラミング言語と同じ言語です):

[ -f /home/user/.bash_profile ] && . /home/user/.bash_profile

ただし、その特定のユーザーが自分のシェルとしてbashを使用しない場合はどうなりますか?彼/彼女はzshkshfishなどを使用する可能性があります。そのため、この方法は、一般向けのプログラムを作成するときには実際には機能しません。

そのため、うまくいくと思われる場合は、~/.bash_profileを入手できます。しかし、ここでは、ファイルを調達できるかどうかではなく、システムでどのように機能するかが重要です:設計コンセプト。要するに:bashを、シェルとプログラミング言語の2つの役割を持つものと見なす必要があります。そうすれば、すべてがはるかに理解しやすくなります。

1
Bach Lien

NVMを使用するcronからノードアプリケーションを実行するときにも同じ問題が発生しました。bashシェルで.bashrcファイルをcronから読み取るには、対話型のシェルオプション `-lを指定してbashコマンドを呼び出すだけです。

例:* * * * * /bin/bash -lc '/home/user/myapp.sh restart'

それが機能しない場合は、crontabでパス変数を設定してみてください

41 7 * * * /bin/bash -lc "PATH=$PATH:/home/user/.nvm/versions/node/v8.10.0/bin && /home/user/script.sh restart "
0
Shyam Jos