目標:Sudoを使用して、1行のcmdを実行し、文字列が見つかるまでログを追跡してから、0を終了します。指定された文字列内に文字列が見つからない場合タイムアウトし、0以外を終了します。
試行された解決策1:元々、要件としてタイムアウトがなかったため、いくつかの調査の後、次のものを使用することにしました。
_Sudo sh -c '( tail -n1 -f /path/to/nameOfLog.log & ) | grep -q "Started .*Application"'
_
ただし、現在、要件としてタイムアウトがあります。 OndraŽižkaの答え が見つかるまで、このコマンドを使用してタイムアウトを取得する方法を理解できませんでした。したがって、私の新しいcmdは次のようになりました。
解決策2を試みます:
timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)
しかし、これは明らかにSudo権限を使用していません。これは、私が解決する必要のある現在の問題です。以下は私が試したが失敗したいくつかのバリエーションです
1を試してください:(cmdの前にSudoを追加してください)
_Sudo timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)
_
出力:
_grep: /dev/fd/63: No such file or directory
_
2:を試してください(cmdをサブシェルでラップしてみてください)
_Sudo sh -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
_
出力:
_sh: 1: Syntax error: "(" unexpected
_
誰かが私に見せて、問題とそれを修正する方法を説明して、sudoを使用してこのコマンドを実行できるようにすることはできますか?また、タイムアウトで動作させるために、試行されたソリューション1からcmdを再構築する必要が本当にありますか?
見つかりました Alexander Batischevの回答Sudo su -c
を使用します。
ソリューション(旧):
Sudo su -c 'timeout 200 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
更新:
ilkkachuの答え に基づいて、私はさらにいくつかのテストを行い、新しい解決策を見つけました。
まず、Sudo su
が冗長であるというilkkachuの回答に応えて。コマンドからSudo
を削除すると、パスワードの入力を求められます。
第二に、サブシェルが役に立たないというilkkachuの回答に応えて。これは本当です。ただし、サブシェルのないコマンドは、何らかの理由でログがアクティブに書き込まれている場合にのみ返されます。それ以外の場合はハングします。サブシェルを使用すると、ログがアクティブに書き込まれていない場合でも、cmdが返されます。したがって、私はサブシェルコマンドを好みますが、sh
はサブシェルをサポートしていません。
また、アクティブログでテストしたときに、bash
とsh
の使用の時間が異なることに気付きました。何らかの理由で、sh
はbash
よりも応答に1秒長くかかります。
これらの2つの理由(サブシェルとsh
の遅延をbash
よりも使用)のために、私はsh
が適切なソリューションではないと判断しました。
第三に、不必要な&for tail
に関するilkkachuの回答に応えて。それは正しいです、私はそれを削除しました、そしてそれは影響を与えませんでした。
概要:
Sudo su vs.su
//prompts for password w/out Sudo
su -c 'timeout 200 grep -q "Started .*Application" <(tail -n100 -f /path/to/nameOfLog.log &)''
//works
Sudo su -c 'timeout 200 grep -q "Started .*Application" <(tail -n100 -f /path/to/nameOfLog.log &)'
sh -cを使用
//either works (Sudo or not using Sudo)
//but both won't work unless log is actively being written to for some reason
Sudo sh -c 'tail -n100 -f /path/to/nameOfLog.log | grep -q "Started .*Application"'
sh -c 'tail -n100 -f /path/to/nameOfLog.log | grep -q "Started .*Application"'
bashを使用
//either works (Sudo or not using Sudo)
Sudo bash -c 'timeout 5 grep -q "Started .*Application" <(tail -n100 -f /path/to/nameOfLog.log &)'
bash -c 'timeout 5 grep -q "Started .*Application" <(tail -n100 -f /path/to/nameOfLog.log &)'
新しい解決策:
重要な詳細を1つ省略していることに気づきました。これは、 terraform remote-execプロビジョナー を介して実行されていたということです。 Terraformは、サーバー上の/ tmp /の下に inline コマンド用のローカル.shスクリプトを作成します。 communicator/ssh/communicator.go スクリプトの先頭に#!/bin/sh
を設定します。これは、スクリプトがsh
を使用していることを意味します。サブシェルを使用しているので、bashを使用する必要があります。須藤の使用は必要ではなく、私の誤解でした。ただし、Sudoは引き続き使用できます。したがって、私が行った答えは、上記の概要の下にリストされているusing bashコマンドのいずれかです。
P.S。この場合のターゲットサーバーは実行されていました14.04.1-Ubuntu。 ls -l /bin/sh
を実行すると/bin/sh -> dash
が表示されるので、実際にはsh
ではなくダッシュを使用しています。したがって、dash
にはsh
と同じ挫折があるようです。
1)ここでサブシェル(またはバックグラウンド)が役立つかどうかはわかりません:
_Sudo sh -c '( tail -n1 -f /path/to/nameOfLog.log & ) | grep -q "Started .*Application"'
_
単純なパイプはすべきではありませんか?
_Sudo sh -c 'tail -n1 -f /path/to/nameOfLog.log | grep -q "Started .*Application"'
_
2)あなたの「トライ1」:
_Sudo timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)
_
Sudo
内ではなく、Sudo
を実行するコマンドラインで入力リダイレクト<()
を展開します。開くファイルハンドルはSudo
からgrep
に渡されないため、grep
は_/dev/fd/63
_疑似ファイルを開くことができません。
ここでtail
を背景にすることについて同じことですが、それは必要ではないはずです。
3)そして、 phkコメント のように、あなたの「try 2」:
_Sudo sh -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
_
...明示的にsh
を実行し、bash
やその他のより機能的なシェルは実行しません。プレーンな標準sh
は<()
をサポートしていません。また、DebianとUbuntuでdash
として使用されるsh
もサポートしていません。
代わりにsu
を実行すると、root
のログインシェルが実行されます。これはUbuntuではbash
である可能性があります。ただし、Sudo
とsu
の両方を使用することは冗長であり、どちらも特権を昇格させるために作成され、Sudo
の後はすでに実行されています昇格された特権なので、su
は必要ありません。代わりに、Sudo
内でシェルを実行する場合は、次のいずれかを明示的に指定してください。
_Sudo bash -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
_