週末の間、バックグラウンドで3つのSASプログラムが実行されています。これら3つのプログラムは同じ名前のファイルに情報を出力するため、最初のプログラムが完了してから2番目のプログラムが開始する前に、2番目のプログラムが完了した後に3番目のプログラムが開始される前にこれらの出力ファイルを削除する必要があります。明らかに、この問題を解決する最も簡単な方法は、出力ファイル名が異なるように各プログラムを変更することですが、Unixの使い方を学ぶのには役立ちません。これが私が今まで得たものです:
# Begin by running the first SAS program in the background.
sas program1.sas & | at 5:00 PM JAN 11
# I'd like to wait until the first program finishes to remove
# the output files and run the second program.
wait ???
rm file1.sas7bdat file2.sas7bdat file3.sas7bdat file4.sas7bdat file5.sas7bdat
sas program2.sas & | at 5:00 PM JAN 12
# And now I repeat.
wait ???
rm file1.sas7bdat file2.sas7bdat file3.sas7bdat file4.sas7bdat file5.sas7bdat
sas program3.sas & | at 5:00 PM JAN 13
私は2つの理由で各プログラムを連続して同時に実行するように設定しました。 (1)以前のプログラムが24時間以内に完了することがわかり、(2)サーバーの負荷が連続的に似ているとします。理想的には、何らかの方法で最初のプログラムのプロセスIDを取得して最初のコマンドに渡すことができ、2番目のプログラムと同じコマンドに渡すことができますwait
。wait
どんなアイデアがありますか?
編集する
wait
この特定のケースではなく、プロセスIDを確認してコマンドに渡す一般的なソリューションに興味があります。
答え1
問題は、実際に使用してはいけないタスクを実行するためにatを使用していることです。また、「プログラム1の後にプログラム2を実行する」と「1月12日午後5時にプログラム2を実行する」という2つの矛盾する目標があります。
問題の一部は簡単に解決できます。 at では複数のコマンドを使用できます。したがって、これを使用してスクリプトをat
スケジュールするsas
だけでなく、タスクに入れることもできますrm
。
at 5:00 PM JAN 11 <<EOJ
sas program1.sas
rm file1.sas7bdat file2.sas7bdat file3.sas7bdat file4.sas7bdat file5.sas7bdat
EOJ
&
キューに入れる理由はありませんsas
。at
ジョブは常に「バックグラウンドで」実行されます。
次に、前述の競合をどのように解決したいかを把握する必要があります。特に、1月11日の作業が24時間以降(1月12日午後5時まで)まで完了していない場合。この問題を解決する方法はいくつかあります。
- これは1月12日の仕事ではありません。 program1.sasが完了したらすぐに実行する必要があります。この場合は、上記の最初の割り当ての一部として作成してください
rm
。 - これは決して起こらないでしょう。その場合は手動で修正してください。このような場合は、上記のように整理すればよいです。
- 待つ必要があります。この場合、最初の操作の終わりにスケジュールしたり、ロックファイルを使用したり、適切な節電時間を計算したりできます(または直接
sleepenh
計算を実行したくない場合は、利用可能な場合を使用してください)。
答え2
したがって、やるべきこととしたいことは基本的に次のように要約されます。
command1 &
wait <on command1>
sleep <until specified time>
command2 &
wait <on command2>
sleep <until specified time>
...
この場合、背景(&
)とwait
およびを削除すると、sleep
コマンドは順番に実行されます。しかし、これはすぐに実行されます。
特定の時間まで待つには、sleep
適切な時間を待つだけです。sleep
入力には数秒かかり、Unixシステムは伝統的に数秒単位で時間を保存して測定するため、これは単純な算術で要約されています。
- 待機日時をエポック以降の秒単位に変換します。
- 現在時刻をエポック以降の秒に変換します。
- 違いを計算してみてください。
- 長すぎる。
これを行う方法このスタックオーバーフローの回答しかし、重要な部分をコピーしてください。
current_epoch=$(date +%s)
target_epoch=$(date -d '01/01/2010 12:00' +%s)
sleep_seconds=$(( $target_epoch - $current_epoch ))
sleep $sleep_seconds
この特定の例はbash構文ですが、すべてのシェルスクリプト言語に簡単に変換する必要があります。$(...)
コマンドを実行し、そのコマンドの出力を置き換え、$(( ... ))
算術式を評価します。
GNUは時間専用のタイムスタンプもサポートしているため、これを今後の05:00に変換するとdate -d
言うことができます。date -d '05:00'
これをまとめると、必要なスクリプトを簡単に作成できます。
答え3
まあ、順序はありませんwait
。少なくとも私が知っている限りではありません。私の代替ロジックは次のとおりです。
各SASプログラムに対して3つのスクリプトファイルを作成します。これらのスクリプトは、以前の sas プログラムの実行が完了した後にのみ実行されます。pid
以前のsasプログラムをキャプチャしてps
コマンドを使用して出力ファイルを削除する前に、そのプログラムが実行されなくなっていることを確認してください。
crontab
毎週金曜日から日曜日までスクリプトを実行するようにスケジュールします。
したがって、最初のスクリプトファイルの名前を指定すると、sas_script1.sh
次のようになります。
if [ -f /var/run/sas.pid ]; then
/bin/ps $( cat /var/run/sas.pid ) >/dev/null
[ $? ] && exit # $? checks the exit status of the last command
fi
rm -f /path/to/file{1..5}.sas7bdat
/usr/bin/sas /path/to/program1.sas &
echo $! >/var/run/sas.pid # $! gives you the PID of the last program that's sent background
両方のSASプログラムの残りの部分に対して同じスクリプトを作成します。たとえば、次のようprogram1.sas
に編集します。program2.sas
1つを作成し、file
その中に次の内容を作成します。
00 17 * * 5 /path/to/sas_script1.sh
00 17 * * 6 /path/to/sas_script2.sh
00 17 * * 0 /path/to/sas_script3.sh
次に、ファイルをcronジョブとしてアップロードします。
crontab /path/to/file
Un*X の詳細をご覧ください。 :D