目标:使用 sudo 执行一行 cmd 来跟踪日志,直到找到字符串,然后退出 0。如果在给定超时内未找到该字符串,则退出除 0 之外的任何内容。
尝试的解决方案1:最初我没有超时作为要求,所以经过一些研究后我决定使用:
sudo sh -c '( tail -n1 -f /path/to/nameOfLog.log & ) | grep -q "Started .*Application"'
但是,现在我确实有超时要求。我无法弄清楚如何让超时来使用此命令,直到我发现Ondra Žižka 的回答。所以我的新命令变成了:
尝试解决方案 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让它也能超时工作?
答案1
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
,没有必要。
3)并且,作为PHK 评论,你的“尝试2”:
sudo sh -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
...显式运行sh
,而不是bash
或任何其他更具功能的 shell。普通标准sh
不支持<()
,也不支持Debian 和 Ubuntu 上dash
使用的。sh
相反,当您运行时su
,它会运行root
的登录 shell,该 shell 可能位于bash
Ubuntu 上。但同时使用sudo
和su
是多余的,它们都是为了提升权限而设计的,之后sudo
你已经在运行提升的权限,所以不需要su
.相反,如果您想在 内部运行 shell sudo
,只需明确说明是哪个:
sudo bash -c 'timeout 5 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
答案2
成立亚历山大·巴蒂舍夫的回答使用sudo su -c
.
解决方案(旧):
sudo su -c 'timeout 200 grep -q "Started .*Application" <(tail -n1 -f /path/to/nameOfLog.log &)'
更新:
基于伊尔卡丘的回答我做了更多测试并找到了新的解决方案。
首先,针对伊尔卡楚的回答关于
sudo su
多余的问题。如果我sudo
从命令中删除,系统会提示我输入密码。二、针对伊尔卡楚的回答有关子外壳没有用的问题。这是真实的。但是,只有在由于某种原因正在主动写入日志时,不带子 shell 的命令才会返回。否则它会挂起。使用子 shell 时,即使没有主动写入日志,cmd 也会返回。所以我更喜欢 subshell 命令,但
sh
不支持 subshell。另外,我注意到在对活动日志进行测试时,使用 using
bash
与using 的sh
时间不同。由于某种原因,sh
需要多花一秒钟的时间才能做出反应bash
。由于这两个原因(使用 subshell 和延迟
sh
overbash
),我认为sh
这不是合适的解决方案。三、针对伊尔卡楚的回答关于不必要的 & for
tail
。是的,我把它删除了,没有影响。
概括:
sudo su 与 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 远程执行配置程序。 Terraform 在服务器上的 /tmp/ 下创建本地 .sh 脚本,用于任何排队命令。这通讯器/ssh/communicator.go设置#!/bin/sh
在脚本的顶部,这意味着它们正在使用sh
.因此,由于我使用的是子 shell,所以我需要使用 bash。使用 sudo 是没有必要的,这是我的误解。但是,您仍然可以使用 sudo。所以我的答案是使用bash上面“摘要”下列出的命令。
聚苯乙烯在这种情况下我的目标服务器正在运行14.04.1-Ubuntu。跑步ls -l /bin/sh
节目/bin/sh -> dash
所以实际上我没有使用sh
而是破折号。所以它看起来也dash
有同样的挫折sh
。