Grep

bash 語法 - 將命令包裝在 sudo :: tail 日誌中,直到使用 Terraform 找到超時的字元串

  • November 23, 2018

**目標:**使用 sudo 執行一行 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包裝在子shell中)

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 的回答,我做了更多的測試並找到了一個新的解決方案。

  1. 首先,回應ilkkachu關於冗餘的回答sudo su。如果我sudo從命令中刪除,系統會提示我輸入密碼。
  2. 其次,為了回應ilkkachu關於 subshel​​l 沒有用的回答。這是真的。但是,僅當由於某種原因正在主動寫入日誌時,沒有子 shell 的命令才會返回。否則它會掛起。使用 subshel​​l 時,即使沒有主動寫入日誌,cmd 也會返回。所以我更喜歡 subshel​​l 命令,但sh不支持 subshel​​l。

此外,我注意到在對活動日誌進行測試時,使用bash與使用的sh時間不同。出於某種原因sh,響應時間要長一秒鐘bash

由於這兩個原因(使用 subshel​​l 和延遲shover bash),我決定sh不是合適的解決方案。 3. 第三,針對ilkkachu關於不必要的 & for 的回答tail。這是正確的,我刪除了它,它沒有任何影響。

概括:

sudo 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 &)'

新解決方案:

我意識到我遺漏了一個重要的細節。也就是說,這是通過terraform remote-exec provisioner 執行的。Terraform 在伺服器上的 /tmp/ 下為任何內聯命令創建一個本地 .sh 腳本。communicator/ssh/communicator.go設置#!/bin/sh在腳本的頂部,這意味著它們正在使用sh. 因此,由於我使用的是子外殼,因此我需要使用 bash。sudo 的使用不是必需的,這是我的誤解。但是,您仍然可以使用 sudo。所以我選擇的答案是上面總結下列出的使用 bash命令。

PS在這種情況下,我的目標伺服器正在執行14.04.1-Ubuntu。執行ls -l /bin/sh節目/bin/sh -> dash,所以實際上我沒有使用sh但破折號。因此,它似乎dashsh.

1)我不確定子shell(或後台)是否在這裡有用:

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. 它打開的文件句柄沒有傳遞sudogrep,因此grep無法打開/dev/fd/63偽文件。

這裡的背景也是一樣的tail,它不應該是必要的。


  1. 而且,正如phk 評論的那樣,您的“嘗試 2”:
sudo sh -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'

…明確執行sh,而不是bash或任何其他更有特色的外殼。普通標準sh不支持<()dashshDebian 和 Ubuntu 上也不支持。

su相反,當您執行時,它會執行root的登錄 shell,這很可能bash在 Ubuntu 上。但是同時使用sudoandsu是多餘的,它們都是用來提升權限的,並且在sudo 你已經執行提升的權限之後,所以不需要su. 相反,如果你想在裡面執行一個 shell sudo,只需明確地說出哪一個:

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

引用自:https://unix.stackexchange.com/questions/317555