bash 語法 - 將命令包裝在 sudo :: tail 日誌中,直到使用 Terraform 找到超時的字元串
**目標:**使用 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 的回答,我做了更多的測試並找到了一個新的解決方案。
- 首先,回應ilkkachu關於冗餘的回答
sudo su
。如果我sudo
從命令中刪除,系統會提示我輸入密碼。- 其次,為了回應ilkkachu關於 subshell 沒有用的回答。這是真的。但是,僅當由於某種原因正在主動寫入日誌時,沒有子 shell 的命令才會返回。否則它會掛起。使用 subshell 時,即使沒有主動寫入日誌,cmd 也會返回。所以我更喜歡 subshell 命令,但
sh
不支持 subshell。此外,我注意到在對活動日誌進行測試時,使用
bash
與使用的sh
時間不同。出於某種原因sh
,響應時間要長一秒鐘bash
。由於這兩個原因(使用 subshell 和延遲
sh
overbash
),我決定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
但破折號。因此,它似乎dash
與sh
.
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
. 它打開的文件句柄沒有傳遞sudo
給grep
,因此grep
無法打開/dev/fd/63
偽文件。這裡的背景也是一樣的
tail
,它不應該是必要的。
- 而且,正如phk 評論的那樣,您的“嘗試 2”:
sudo sh -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
…明確執行
sh
,而不是bash
或任何其他更有特色的外殼。普通標準sh
不支持<()
,dash
在sh
Debian 和 Ubuntu 上也不支持。
su
相反,當您執行時,它會執行root
的登錄 shell,這很可能bash
在 Ubuntu 上。但是同時使用sudo
andsu
是多餘的,它們都是用來提升權限的,並且在sudo
你已經執行提升的權限之後,所以不需要su
. 相反,如果你想在裡面執行一個 shellsudo
,只需明確地說出哪一個:sudo bash -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'