Bash 脚本通过 term 和 MacOS launchd 评估不同

Bash script evaluates differently via term and MacOS launchd

我有一个非常简单的 bash 脚本,它可以卷曲一个 URL,计算响应中的一个子字符串,如果它找到该字符串,运行 就会输入一些代码。

本来我是这样写的:

RESP=$(curl -s 'https://theurl.com' | grep -ic substring)

if [ $RESP > 0 ];
  do something
else
  do something else
fi

这在我的终端提示下效果很好。

当我在 launchd 中将其设置为 运行 作为本地用户启动代理时,if 语句从未评估为真。

我在调试过程中尝试的事情:

  1. 确保两者都像我一样使用 /bin/bash(他们是)和 运行ning。
  2. 将变量发送到标准输出以确认。
  3. 运行 他们没有卷曲,只是 grepping 一个本地文件。

最终,我将 if 更改为:

if [ $RESP -ge 1 ]

这在两个地方都有效,但我不明白为什么完全相同的解释器中的完全相同的脚本在两个地方的计算结果不同。

有什么想法吗?

这是因为 > 并不像您认为的那样。命令

[ $RESP > 0 ]

被 shell 视为一种有趣的写作方式

[ $RESP ] > 0

也就是说,它 运行 是命令 [(是的,这是一个实际的命令,本质上等同于 test)扩展了 $RESP 和“ ]" 作为参数。 > 0[ 的参数中间这一事实无关紧要;您可以将重定向运算符放在命令 ... 参数序列的任何位置,它会做同样的事情。

最终结果:[ 检查 $RESP 是否扩展为非空字符串(如果是则成功),并将其(空)输出发送到名为“0”的文件.

至少,这是它通常所做的。我怀疑当你 运行 它作为启动代理时,它在创建“0”文件时出错,所以它失败了。由于它失败了,并且它是 if 语句的条件,else 子句 运行s.

要在 [ ] 测试表达式中使用 ><,您需要引用或转义它,例如 [ "$RESP" ">" 0 ][ "$RESP" \> 0 ]。另外, > 无论如何都是错误的测试操作符;如果您要比较整数,请改用 -gt。在 [ ] 测试表达式中,> 表示排序顺序比较(因此 [ 9 ">" 10 ] 为真,因为“9”排在“1”之后)。

这看起来很奇怪,但正如 Cyrus 在评论中指出的那样,命令 [ $RESP > 0 ] 创建了一个名为 0 的文件。如果您 运行 launchd 中的脚本创建此类文件可能会失败,因为工作目录与您 运行 终端中的脚本不同。因为无法创建文件,if ...检查失败,进入else分支。

现在,到底为什么要创建一个文件。 bash -c 'help test'[test 的同义词)明确指出

STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.

但是,在 test/[ 看到 > bash 处理它并将其解释为重定向之前。下面三个命令其实是等价的:

echo string > file
echo > file string 
> file echo string

因此,您进行测试 [ $RESP ] 并将(空)输出重定向到文件 0.

要使用 test 中的 >,您必须引用它,例如:[ $RESP ">" 0 ]。但是,正如您已经注意到的,您想改用 -gt

注意: 要检查是否找到任何匹配项,您可以改用 grep -q

if curl -s 'https://theurl.com' | grep -iq substring; then
  # do something
else
  # do something else
fi