shell脚本中的while循环

shell脚本中的while循环

我可以运行 count 命令,但是当我在 while 条件下使用它时,它会给出错误:

-bash: [/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86-64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l: No such file or directory.


count="/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86- 
64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l"
while [ "$count" -ne 0 ]
do
echo "killing services and tomcat process"
/usr/bin/ps -aef|/usr/bin/egrep "catalina|java|wrapper-linux-x86- 
64"|/usr/bin/grep -v "catalina|java"|/usr/bin/awk '{print 
$2}'|/usr/bin/xargs kill -9
sleep 10
count="/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86- 
64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l"

done;

答案1

count="/usr/bin/ps -aef|...|wc -l"

不要将命令存储在变量中,它们不是为此而设计的,并且使用存储的命令很困难。如果您想将命令存储在某处,请使用函数:

count_procs() {
    /usr/bin/ps -aef|...|wc -l
}

函数可以像任何其他命令一样使用。

您显示的代码将将该字符串的值count与整数零进行比较。 Bash[会抱怨非数字值。

您提出的错误可能来自类似的命令(和["$count" -eq 0 ]之间没有空格),因为在这种情况下, 的内容会连接起来形成命令行的第一个单词,即要运行的命令的名称。虽然这样做很愚蠢,但完全有可能拥有包含括号、竖线字符和空格的路径。[$countcount[

现在,假设您想要实际运行该命令并捕获其输出以与零进行比较,您将需要使用命令替换$(...)

result=$(ps ... |wc -l)            # save the output of the command to `result`

或者

[ "$(ps ... | wc -l)" -eq 0 ] ... # use the command output directly in a test

假设您想要在每次循环运行时对进程进行计数,则必须在循环体内运行该命令。所以,例如

while [ "$(ps ... | wc -l)" -eq 0 ]; do
    ...
done

或者,用一个函数

count_procs() {
    /usr/bin/ps -aef|...|wc -l
}
while [ "$(count_procs)" -eq 0 ]; do
    ...
done  

只要在循环之前对进程进行一次计数就会使条件成为常数,并且循环将无限期地重复,或者根本不重复。

答案2

在 while 循环中,您需要减少 count 变量。

count=10
while [ $count -ne 0 ]; do
    echo "Count is $count"
    ((count--))
done

对于实际的算术,有多种方法可以实现,例如:

  • ((count--))
  • ((count-=1))
  • ((count=count-1))
  • count=$((count - 1))

有关双括号结构的更多信息,请参阅:https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/dblparens.html

您还可以使用let

  • let "count--"
  • let "count-=1"
  • let "count=count-1"

有关 的更多信息let,请参阅:http://wiki.bash-hackers.org/commands/builtin/let


编辑:关于 POSIX 兼容 shell 的注释,这些 shell 不具有与bash.

Posix shell 可以使用该$(( <expression> ))语法。因此,如果您有上面相同的循环,并且您想确保它可以在像kshCAE Issue 4 (XPG4) 这样的 shell 或官方便携式 shell上工作sh

  • count=$((count - 1))

如果这对您很重要,那么使用此语法将使您的脚本比使用 bash 特定语法更具可移植性。

答案3

除了命令替换引用的混乱之外,错误消息还表明您实际上while ["$count" -ne 0]在括号周围没有所需的空间。请记住,“while”之后的部分实际上是命令,并且循环结束时命令以非零状态退出(参考https://www.gnu.org/software/bash/manual/bashref.html#Looping-Constructs)。

由于缺少空格,bash 看到

while ["/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86-64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l" -ne 0]

它正在尝试执行命令 ["/usr/bin/ps -aef|...|wc -l"显然没有找到

重要的是要记住这[实际上是一个命令因此,需要在命令名称后面添加一个空格来将命令名称与其第一个参数分隔开。 (与你写ls -l和不写的原因相同ls-l)。该命令还[要求这]是它的最后的参数,因此]也需要空格分隔。

在 bash 提示符处,键入help [and help test(还有help [[

答案4

您的主要问题是使用双引号,其中应有:

$(...)

我对此部分有一些评论(评论太长):

while [ "$count" -ne 0 ]
do
echo "killing services and tomcat process"
done;

  • 循环没有停止机制,while例如:

    count=$(( count - 1 ))
    
  • 从造型角度来说,你应该内部空间。

  • 请注意,末尾不需要分号。

相关内容