bash 语法 - 将命令包装在 sudo :: tail 日志中,直到使用 Terraform 找到超时的字符串

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 的回答。所以我的新命令变成了:

尝试解决方案 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.它打开的文件句柄不会传递到sudogrep因此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 可能位于bashUbuntu 上。但同时使用sudosu是多余的,它们都是为了提升权限而设计的,之后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 &)'

更新:

基于伊尔卡丘的回答我做了更多测试并找到了新的解决方案。

  1. 首先,针对伊尔卡楚的回答关于sudo su多余的问题。如果我sudo从命令中删除,系统会提示我输入密码。

  2. 二、针对伊尔卡楚的回答有关子外壳没有用的问题。这是真实的。但是,只有在由于某种原因正在主动写入日志时,不带子 shell 的命令才会返回。否则它会挂起。使用子 shell 时,即使没有主动写入日志,cmd 也会返回。所以我更喜欢 subshel​​l 命令,但sh不支持 subshel​​l。

    另外,我注意到在对活动日志进行测试时,使用 usingbash与using 的sh时间不同。由于某种原因,sh需要多花一秒钟的时间才能做出反应bash

    由于这两个原因(使用 subshel​​l 和延迟shover bash),我认为sh这不是合适的解决方案。

  3. 三、针对伊尔卡楚的回答关于不必要的 & 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

相关内容