web-dev-qa-db-ja.com

bash構文-Sudo内でコマンドをラップする:: Terraformを使用してタイムアウトで文字列が見つかるまでテールログ

目標: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を再構築する必要が本当にありますか?

4
mdo123

見つかりました Alexander Batischevの回答Sudo su -cを使用します。

ソリューション(旧):

Sudo su -c 'timeout 200 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'

更新:

ilkkachuの答え に基づいて、私はさらにいくつかのテストを行い、新しい解決策を見つけました。

  1. まず、Sudo suが冗長であるというilkkachuの回答に応えて。コマンドからSudoを削除すると、パスワードの入力を求められます。

  2. 第二に、サブシェルが役に立たないというilkkachuの回答に応えて。これは本当です。ただし、サブシェルのないコマンドは、何らかの理由でログがアクティブに書き込まれている場合にのみ返されます。それ以外の場合はハングします。サブシェルを使用すると、ログがアクティブに書き込まれていない場合でも、cmdが返されます。したがって、私はサブシェルコマンドを好みますが、shはサブシェルをサポートしていません。

    また、アクティブログでテストしたときに、bashshの使用の時間が異なることに気付きました。何らかの理由で、shbashよりも応答に1秒長くかかります。

    これらの2つの理由(サブシェルとshの遅延をbashよりも使用)のために、私はshが適切なソリューションではないと判断しました。

  3. 第三に、不必要な&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-Ubuntuls -l /bin/shを実行すると/bin/sh -> dashが表示されるので、実際にはshではなくダッシュを使用しています。したがって、dashにはshと同じ挫折があるようです。

0
mdo123

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である可能性があります。ただし、Sudosuの両方を使用することは冗長であり、どちらも特権を昇格させるために作成され、Sudoの後はすでに実行されています昇格された特権なので、suは必要ありません。代わりに、Sudo内でシェルを実行する場合は、次のいずれかを明示的に指定してください。

_Sudo bash -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
_
0
ilkkachu