crontabを使用して自動的に実行すると、このスクリプトが破損したファイルを出力するのはなぜですか?

crontabを使用して自動的に実行すると、このスクリプトが破損したファイルを出力するのはなぜですか?

フォルダ内のすべての.mp3ファイルを検索してインデックスを作成するスクリプトがあります。それから5秒待ってください。それ以外の場合は正常に動作しません。最後に、曲のタイトルから誤った文字を削除します。

sudo crontabを使用して自動的に実行します。

#!/bin/bash
#Creates index file.
find /var/www/html/uploads/Music/ -name '*.mp3' > /var/www/html/uploads/Music/songs.index | sleep 5s | sudo sed -i -e 's/\/var\/www\/html/\.\./g' /var/www/html/uploads/Music/songs.index

何らかの理由でcrontabを実行すると、テキストに変換され、再度索引付けされる必要がある読み取り可能なファイルが生成されます。同じスクリプトを手動で実行すると正常に動作します。私は何を見逃していますか?

クローンタブファイル:

1 * * * * /home/aaeadmin/bin/midnightRun.bash

ベストアンサー1

これは可能パイプラインでコマンドを実行しているからです。

パイプラインの各部分は、同じパイプラインの他の部分と同時に開始して実行されます。これはfind、そのコマンドがこのコマンドとまったく同時に開始されたことを意味しますsed。パイプ(あるコマンドの標準出力から次のコマンドの標準入力まで)を介して渡されたデータのみ、別のコマンドを同期できます。

また、実際にはそうではありません。使用配管の配管側。コマンド間でデータは渡されません。

あなたのスクリプトは次のように書くのが最善です。

#!/bin/bash
#Creates index file.

find /var/www/html/uploads/Music/ -name '*.mp3' > /var/www/html/uploads/Music/songs.index

sed -i -e 's/\/var\/www\/html/\.\./g' /var/www/html/uploads/Music/songs.index

これで、findコマンドが開始される前にコマンドの実行が完了しますsed。また、これらのsudoコマンドは明らかに不要なので削除しました(findファイルを書き込めなくてもsed読み込み、修正できますsudo)。

お探しの場合するsudo書き込みが必要な場合は、ターゲットsongs.indexディレクトリに書き込み権限を持つユーザーのcrontabでこのcronジョブを実行することをお勧めします/var/www/html/uploads/Music

パイプラインソリューション

#!/bin/sh
#Creates index file.

find /var/www/html/uploads/Music/ -name '*.mp3' |    
sed -e 's,^/var/www/html,..,' >/var/www/html/uploads/Music/songs.index

ここにfind書いたまっすぐコマンドを実行しsedsedコマンドの結果をインデックスファイルに書き込みます。からのfindデータ(パス名)通信は、sed両方のプロセスを同期状態に保ちますsed待つ続行する前に、次の入力ラインを生成するために使用されます(またはその逆の場合、よりfind多くのデータを出力する前にデータが処理されるのfindを待ちますsed)。

また、コマンドを読みやすくし、正規表現を行の先頭sedに固定し、g最後から不要なフラグを削除しました。これで、findコマンドから読み取られたため、その-iオプションも削除されました(技術的にはその-eオプションも削除できます)。

私が変えたもう一つのことは配線でした#!。特定の機能を使用しないので、bash(おそらく)より軽​​いシェルを使用してスクリプトを実行することもできます。

見つかったファイルのファイル名をインデックスに記録して最初の文字を変更するには、次のよう/var/www/html..直接実行することもできますfind

#!/bin/sh
#Creates index file.

find /var/www/html/uploads/Music/ -type f -name '*.mp3' -exec sh -c '
    for pathname do
        printf "../%s\n" "${pathname#/var/www/html/}"
    done' sh {} + >/var/www/html/uploads/Music/songs.index

このfindコマンドは、指定されたパターンと一致するすべての一般ファイル(ディレクトリなどではない)のパス名を検索します。これらのパス名のバッチに対して短いインラインシェルスクリプトが呼び出されます。スクリプトは現在のパス名の配置を繰り返し、少し変更して印刷します。

パス名の変更はパラメータ置換によって行われます${pathname#/var/www/html/}。これ削除/var/www/html/の値から始まる文字列です$pathname。使用されたフォーマット文字列はprintfこの部分が../

また、見ることができます

おすすめ記事