/ 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"を実行するだけではありませんか?
ジョブの実行中のユーザーに対して、スクリプトの先頭またはジョブの先頭で必要なファイルを入手できます。 「ソース」コマンドは組み込みです。これらのファイルを編集して変更を読み込む場合も、同じことを行います。
* * * * * source /home/user/.bash_profile; <command>
または
#!/bin/bash
source /home/user/.bash_profile
<commands>
それはインタラクティブなシェルではないからです。一部のターミナルを開いたときにも同じことが起こります。
この質問を見てください: 。bashrcファイルとは何ですか?|スーパーユーザー
そしてこれでも:
。bashrc、.bash_profile、.environmentの違いは何ですか?| Stack Overflow
接続がログインシェル(またはそうでない)、インタラクティブシェル(またはそうでない)、またはその両方であるかどうかに応じて、異なるスクリプトが起動します。
Bashrcを作成する場合は、次の変更を行う必要があります。
Bashが非対話的に起動されると、たとえば、シェルスクリプトを実行するために、環境内で変数BASH_ENVを探し、そこに表示されている場合はその値を展開し、展開された値をファイルの名前として使用して読み取りおよび実行します。 Bashは、次のコマンドが実行されたかのように動作します。
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
ただし、PATH変数の値は、ファイル名の検索には使用されません。
上記のように、非インタラクティブシェルが
--login
オプション、Bashはログインシェルの起動ファイルからコマンドを読み取って実行しようとします。
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に変更)する方法
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
ソーシングしてもすぐに終了するため、何の役にも立ちません。
次のように、-l
オプションを使用してbashを呼び出すことができます。
* * * * * /bin/bash -l /path/to/script arg1 arg2
-l
オプションは、bashをloginシェルにします。したがって、ユーザーの.bash_profile
を読み取ります。 .bashrc
から明示的に供給されない限り、ユーザーの.bash_profile
は読み取られません。これは、非インタラクティブシェルが.bashrc
を自動的に読み取らないためです。ただし、.bashrc
はinteractiveシェルに役立つものを設定するためのものなので、cronジョブに.bashrc
は必要ありません。
バリエーション:
BashがPATH上にある場合、絶対パスを指定する必要はありません。
* * * * * bash -l /path/to/script arg1 arg2
最適化は、exec
を使用して現在のシェルを置き換えることです。
* * * * * exec bash -l /path/to/script arg1 arg2
bash
は、それがShellでも、通常のプログラミング言語(Perl
やpython
のように)でも、動作が異なります。
設計上、~/.bash_profile
、~/.bashrc
などの設定は、ユーザーがbash
を再生するときに設定するものですシェルの役割(ログインシェル、インタラクティブシェル)。 xterm
(対話型シェル)、ssh
セッション(ログインシェル)、またはコンソール(ログインシェル)の環境について考えてみましょう。
一方、bash
も強力なプログラミング言語 –systemd
でサービスを管理するための多くのスクリプトについて考えてください。これには異なるスタイルの作業が必要です。たとえば、開発者がシステムスクリプトまたはbash
プログラムを作成している場合、ユーザーの~/.bash_profile
を自動的に取得したくありません。シェルではなく、通常のプログラムです。通常のプログラム(bash
プログラムを含む)は当然、現在の作業中の廃止(シェル)からinherit設定になりますが、setではありません。
cron
でbash
のプログラムを作成すると、たまたまbash
で作成されます。実際、python
またはPerl
またはその他のプログラミング言語で書き込むことができます。次に、bash
の~/.bash_profile
をソースにするオプションを使用できます(読み取り:設定ユーザーのシェル、それはたまたまあなたのプログラミング言語と同じ言語です):
[ -f /home/user/.bash_profile ] && . /home/user/.bash_profile
ただし、その特定のユーザーが自分のシェルとしてbash
を使用しない場合はどうなりますか?彼/彼女はzsh
、ksh
、fish
などを使用する可能性があります。そのため、この方法は、一般向けのプログラムを作成するときには実際には機能しません。
そのため、うまくいくと思われる場合は、~/.bash_profile
を入手できます。しかし、ここでは、ファイルを調達できるかどうかではなく、システムでどのように機能するかが重要です:設計コンセプト。要するに:bash
を、シェルとプログラミング言語の2つの役割を持つものと見なす必要があります。そうすれば、すべてがはるかに理解しやすくなります。
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 "