web-dev-qa-db-ja.com

Cronは実行されますが、スクリプトは機能しません

似たような質問がたくさんあることは知っていますし、いろいろ試してみましたが、まだうまくいきません。

10分で実行するようにスケジュールされているcronjobがあります。 /var/log/syslogで、正常に実行されていることがわかります

Oct 21 07:30:01 stan CRON[7604]: (stan) CMD (stan /home/stan/update.sh)
Oct 21 07:40:01 stan CRON[8304]: (stan) CMD (stan /home/stan/update.sh)
Oct 21 07:50:01 stan CRON[8751]: (stan) CMD (stan /home/stan/update.sh)
Oct 21 08:00:01 stan CRON[9347]: (stan) CMD (stan /home/stan/update.sh)
Oct 21 08:10:01 stan CRON[9789]: (stan) CMD (stan /home/stan/update.sh)

update.sh call phpデータベースを更新するスクリプト。ターミナルから直接実行すると、シェルスクリプトデータベースが更新され、完全に機能します。

./update.sh

しかし、cronjobからはデータベースが更新されません。私のcron

*/10 * * * * stan /home/stan/update.sh

シェルスクリプトから生成されるコマンドは

/usr/bin/php /var/www/html/site/update.php

両方のファイルの許可

-rwxrwxr-x  1 stan stan    123 Oct 20 15:09 update.sh
-rwxr-xr-x  1 stan www-data 1301 Oct 21 07:52 /var/www/html/site/update.php

何が問題になるのでしょうか?

更新:PATH

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

update.sh

$ cat update.sh 
#!/bin/sh

list="/var/www/html/site"
config="/usr/bin/php"

for i in "$list"
do
    "$config" "$i"/update.php
done

参照 シェルとphpについてだった昨日からの私の質問はcronについてです。

$ whereis php

php: /usr/bin/php5.6 /usr/bin/php /usr/lib/php /etc/php /usr/include/php /usr/share/php5.6-intl /usr/share/php7.0-mbstring /usr/share/php7.0-common /usr/share/php5.6-curl /usr/share/php5.6-Gd /usr/share/php5.6-mcrypt /usr/share/php5.6-common /usr/share/php5.6-readline /usr/share/php5.6-json /usr/share/php /usr/share/php5.5-mbstring /usr/share/php5.6-opcache /usr/share/php5.6-mbstring /usr/share/php5.6-xml /usr/share/php5.5-common /usr/share/php5.6-mysql /usr/share/man/man1/php.1.gz

$ which php
/usr/bin/php
4
S.I.

cronジョブを呼び出す2つの異なる方法を混同しているようです。

Ubuntuは、スプール領域/var/spool/cronに格納されているユーザーcrontabsと、/etc/crontabおよび/etc/cron.dのファイルから実行されるシステム全体のcronジョブの両方をサポートするやや混乱したポリシーをDebianから継承します。

/etc/crontabで指定されたジョブまたは/etc/cron.dのファイルを介して指定されたジョブは、別のユーザーとして実行できるように追加のフィールドが必要なので、形式は次のようになります。

*/10 * * * * <username> <command> <args>

crontab -e(またはルートの場合はSudo crontab -e)を使用してスプール領域を介してセットアップされたジョブは、すでに特定のユーザーに属しているため、ユーザーフィールドは不要です。

*/10 * * * * <command> <args>

crontab -eコマンドを介して設定されたcronジョブにユーザー名フィールドを含めると、コマンドとして誤って解釈されます。ログ出力からわかるように、

Oct 21 07:30:01 stan CRON[7604]: (stan) CMD (stan /home/stan/update.sh)

cronstancommand with argument/home/stan/update.shとして解釈しています

解決策は、単にcrontabからユーザー名stanを削除することです。

4
steeldriver

考えられるいくつかの問題:

1)#!/bin/shの最初の行にupdate.shがない場合があります

2)PHPは追加のコマンドを実行する必要がある場合がありますが、cronジョブはPATH変数を設定せずに実行されます。これを修正するには、コマンドが機能する端末でecho $PATHを使用してからexport PATH=...を使用し、...を上記のecho $PATHの出力に置き換えます

3)PHPは、機能するために他の環境変数を必要とする場合があります。それらを追跡し、update.shを呼び出す前に/usr/bin/phpにエクスポートします。

編集

OK、そうではありません1)

新しいウィンドウ(または新しいssh接続)を開き、次を実行します。

for i in `env | sed 's/=.*//'` ; do unset $i ; done

これにより、PATHを含むすべての環境変数が設定解除されます。次に試してください:

/usr/bin/php /var/www/html/site/update.php

次に、エラーメッセージをここに投稿します。

2
sмurf

問題は、crontabの非常に限られたパス変数検索です。すべてのスクリプトおよび下付き文字のほとんどすべてのコマンドに追加するには、フルパスを追加する必要があります。または、スクリプトを手動で実行するときと同じ検索パスをスクリプトに追加できます。

変更元:

#!/bin/sh

list="/var/www/html/site"
config="/usr/bin/php"

for i in "$list"
do
    "$config" "$i"/update.php
done

変更先:

#!/bin/sh

PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

list="/var/www/html/site"
config="/usr/bin/php"

for i in "$list"
do
    "$config" "$i"/update.php
done

追加されたパス検索は、質問で投稿したものから取得されたもので、スクリプトを手動で実行すると機能します。 update.phpスクリプトによって呼び出されるスクリプトまたはコマンドとともに、スクリプトからのコマンドが含まれるパスがわかっている場合、追加する必要があるのはそれらの検索パスのみです

2
L. D. James