私はGoogleにアクセスするための特別な方法を使用しています。これでページが大きく変わりました。したがって、通常は質問を編集し、答えにコメントすることができます。以前のディスカッションをさらに削除し、ポイントを整理しました。
スクリプトが次のコマンドを実行するキーワードを見つけたら、テーリングを停止して0を返したいと思います。 1分後にキーワードが見つからない場合は、スクリプト全体が停止し、エラーコードが返されます。set -euxo pipefail
ぜひ必要で使用しています。
timeout 1m tail -Fn 0 --pid=$(ps -ef | grep "sed /$keywords" | grep -v grep | awk '{print $2}') $log_file | sed "/$keywords/q"
以前に使用した上記のコマンドは、テスト時に正しく接続されました。しかし、Jenkinsでは、キーワードが見つかると、「ビルドステップ 'シェル実行'がビルドを失敗としてマークしました。」を返すことがあります。
プログラムを手動で再起動した後、原因を見つけました。コード141を返します。そのため、コードを確認してみると、tail -f
パイプラインと関連があることがわかりました|
。http://www.pixelbeat.org/programming/sigpipe_handling.html。
私の目的のために他の質問のコマンドを修正しました。 「tail-Fn 0 balabala.log」がまだバックグラウンドに残り、数分後に消えることを除いて、すべてが大丈夫です。しかし、目標に最も近いです。
{ sed /"$keywords"/q; kill -13 $!; } < <(exec timeout 1m tail -Fn 0 $log_file)
これは私が理解できないことです...使用法を探しましたが、それでも確信はありません。
- 代わりにスクリプトを
kill -s PIPE "$!"
短縮しました。kill -13 $!
- まだの使い方が混乱します
{ } < <()
。私にとっては外国語のような言葉です...exec
削除できますか?使わないのとは違うようです。tail
裏面に問題があるのでしょうか?同時に複数のプログラムを起動すると危険ですか?
Jenkinsログは次のとおりです。
......
+ keywords='cloud-service-notice has been started successfully'
+ log_file=/data/jars/logs/info.cloud-service-notice.log
+ cd /data/jars/cloud-service-notice
+ nohup java -jar /data/jars/cloud-service-notice/cloud-service-notice.jar --spring.profiles.active=test
+ sed '/cloud-service-notice has been started successfully/q'
++ exec timeout 1m tail -Fn 0 /data/jars/logs/info.cloud-service-notice.log
2019-07-02 10:31:12,544 [main] INFO o.s.c.a.AnnotationConfigApplicationContext.prepareRefresh[588] - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@54a097cc: startup date [Tue Jul 02 10:31:12 CST 2019]; root of context hierarchy
......
2019-07-02 10:31:33,860 [main] INFO c.enneagon.service.notice.NoticeApp.main[24] - cloud-service-notice has been started successfully
+ kill -13 20021
+ ssh web01 'cd /data/releases/cloud-service-notice/20190702-104108/.. &&' 'ls -1 | sort -r | awk '\''FNR > 20 {printf("rm -rf %s\n", $0);}'\'' | bash'
Finished: SUCCESS
プロセス20021はですtimeout 1m tail -Fn 0 balabala.log
。スクリプトが完了した後も、プロセス20023はtail -Fn 0 balabala.log
まだ存在し、数分後に消えました。
[root@web01 scripts]# ps -ef | grep notice
root 20020 1 27 10:41 ? 00:01:07 java -jar /data/jars/cloud-service-notice/cloud-service-notice.jar --spring.profiles.active=test
root 20023 1 0 10:41 ? 00:00:00 tail -Fn 0 /data/jars/logs/info.cloud-service-notice.log
root 20461 18966 0 10:45 pts/1 00:00:00 grep --color=auto notice
このコマンドで私の質問に答えたいのですが、わかりません。ローカルコンピュータでテストした後、さらにテストするために本番環境に配置しました。
多くのテストの最後に、ついにコマンドを次のように変更しました。
{ sed /"$keywords"/q; kill $!; } < <(exec timeout 1m tail -Fn 0 $log_file)
-13
今削除しました。だから滞在するのですtail -Fn 0 balabala.log
。上記の4つの質問におおよそ答えることができます。
kill -15
このコマンドを追加したので、より良いですtimeout
。$!
うん、pidtimeout
。tail -Fn 0 balabala.log
以下は、デフォルト番号15を使用して終了できる子プロセスです。- プロセス交換とマルチプロセス使用のみです
{...}
。kill
1分後にtimeout
バックグラウンドで自分で終了するため、無視することもできます。したがって、このコマンドは:なしでkill
まだ受け入れられますsed /"$keywords"/q < <(exec timeout 1m tail -Fn 0 $log_file)
。この場合、常に0を返します。- そうでないことをお勧めします。コマンドを実行すると、2つの親プロセスが表示されます。ところでやったら大丈夫だよ。
- その理由は上記の「1」にあります。
timeout
殺されたがtail
残された。
答え1
次のことができます。
sh -c 'echo "$$"; exec tail -f file' | (
IFS= read -r pid
timeout 60 sed "/$keyword/q"
kill -s PIPE "$pid"
)
そのオプションを有効にしないと、それ自体が終了しない限り、終了ステータスは0pipefail
で終了します(実際には発生しないでください)。kill
tail
使用すると、pipefail
SIGPIPEによって終了ステータスが終了しますtail
(値が141のほとんどのシェルに表示されます)。|| true
正常な終了状態を強制するために、いつでもaを追加できます。
また見なさい:
答え2
私の考えでは、ここで何が起こっているのかは競争条件です。シャットダウンのために破損したパイプに書き込もうとしているSIGPIPE(通常128 + 13 = 141シャットダウンステータスに対応する信号13)を受信する前に、追跡されたPIDがシャットダウンしていることを確認して認識tail --pid=...
してください。これtail
sed
手動「プロセスが終了した直後にテールも終了します」としか記載されていないため、確認が頻繁に発生しない場合があります。
とにかくtail
SIGPIPEによって終了した場合、これは(通常)目的の行を取得してsed
終了したことを意味します。返品成功の条件になります。if
回避するには、ブロックを使用しset -e
て終了ステータスを明示的に確認して、まったく同じように処理することをお勧めします。
if timeout tail ... | sed ...; ret=$?; then
: # do nothing, success
elif [ "$ret" != 141 ] # not sigpipe, sed didn't quit, so failure
exit "$ret"
fi
ナレーター:スクリプトが#/bin/bash
。これがなければ、スクリプトはshを使用して実行され、おそらくプロセスオーバーライドを使用しようとしている理由です(はい#!
#
<(...)
プロセス、コマンドではなく置換)は構文エラーです。慎重に確認してください。
シングルライナーが欲しいと言われましたが、複雑なシングルライナーは、保守性の点で常に最善の解決策ではありません。実行中の作業を簡単に記録するには、複数行を使用してください。
答え3
命令が見つかりました。詳細は質問にあります。
{ sed /"$keywords"/q; kill $!; } < <(exec timeout 1m tail -Fn 0 $log_file)
#!/bin/bash
set -euxo pipefail
スクリプトにおよびが必要な場合は、bash
CentOSはスクリプトsh
をに接続せずに実行する必要があります。bash