キューイングの問題の解決策を調査しているときに、この質問に出くわしました。ここで検索している他の人の利益のために、私の解決策があります。
これを、スケジュールどおりにジョブを開始する(同時に実行するようにスケジュールされている場合でも)ジョブを開始するcronと組み合わせて、説明した問題も解決します。
問題
- スクリプトの最大 1 つのインスタンスが実行されている必要があります。
- リクエストをキューに入れ、できるだけ早く処理したいと考えています。
すなわち。スクリプトへのパイプラインが必要です。
解決:
任意のスクリプトへのパイプラインを作成します。小さな bash スクリプトを使用して実行します (さらに下)。
スクリプトは次のように呼び出すことができます
./pipeline "<any command and arguments go here>"
例:
./pipeline sleep 10 &
./pipeline shabugabu &
./pipeline single_instance_script some arguments &
./pipeline single_instance_script some other_argumnts &
./pipeline "single_instance_script some yet_other_arguments > output.txt" &
..etc
スクリプトは、コマンドごとに新しい名前付きパイプを作成します。したがって、上記は名前付きパイプを作成します: sleep
、shabugabu
、およびsingle_instance_script
この場合、最初の呼び出しでリーダーが開始され、引数として実行single_instance_script
さsome arguments
れます。呼び出しが完了すると、リーダーはパイプから次の要求を取得しsome other_arguments
、 、完了、次の取得などで実行します...
このスクリプトはプロセスのリクエストをブロックするため、バックグラウンド ジョブ (& の最後に) として呼び出すか、at
( at now <<< "./pipeline some_script"
)を使用して切り離されたプロセスとして呼び出します。
#!/bin/bash -Eue
# Using command name as the pipeline name
pipeline=$(basename $(expr "$1" : '\(^[^[:space:]]*\)')).pipe
is_reader=false
function _pipeline_cleanup {
if $is_reader; then
rm -f $pipeline
fi
rm -f $pipeline.lock
exit
}
trap _pipeline_cleanup INT TERM EXIT
# Dispatch/initialization section, critical
lockfile $pipeline.lock
if [[ -p $pipeline ]]
then
echo "$*" > $pipeline
exit
fi
is_reader=true
mkfifo $pipeline
echo "$*" > $pipeline &
rm -f $pipeline.lock
# Reader section
while read command < $pipeline
do
echo "$(date) - Executing $command"
($command) &> /dev/null
done