【问题标题】:Bash script evaluates differently via term and MacOS launchd [duplicate]Bash 脚本通过 term 和 MacOS launchd 进行不同的评估 [重复]
【发布时间】:2021-03-01 23:49:41
【问题描述】:

我有一个非常简单的 bash 脚本,它可以卷曲 URL,计算响应中的子字符串,并在找到字符串时运行一些代码。

原来我是这样写的:

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

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

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

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

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

  1. 确保两者都使用 /bin/bash(他们曾经使用过)并像我一样运行。
  2. 将变量发送到标准输出以进行确认。
  3. 在没有 curl 的情况下运行它们,只需 grepping 一个本地文件。

最终,我可以通过将 if 更改为:

if [ $RESP -ge 1 ]

这在两个地方都有效,但我不明白为什么完全相同的解释器中的完全相同的脚本会在两个地方进行不同的评估。

有什么想法吗?

【问题讨论】:

  • [ $RESP > 0 ]; 之后,您缺少then。但是,如果没有then,我希望脚本总是会失败。您只是在问题中错过了它吗?
  • 脚本是否以#!/bin/bash开头?
  • 除非您有充分的理由不这样做,否则请始终引用您的变量。
  • 使用shbash [ $RESP > 0 ] 创建一个名为0 的文件。
  • [[[ 内部 bash 比较的一般规则:对数字使用“字母”比较 -gt,对字符串使用“数字”比较 >,与什么相反你会认为...

标签: bash macos launchd


【解决方案1】:

这是因为> 没有按照您的想法执行。命令

[ $RESP > 0 ]

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

[ $RESP ] > 0

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

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

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

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

【讨论】:

  • 谢谢。我怀疑它与评估语法有关,但我无法弄清楚为什么在我自己的 shell 中工作。这解释了它。如果 launchd 会引发错误,我会很快将其归零。感谢您的 bash 课程!
  • @MichaelM 不幸的是,launchd 作业在没有与用户界面任何连接的情况下运行,因此它们没有报告错误的好方法。对于调试,您可以通过将 StandardOutPathStandardErrorPath 键添加到 .plist 来将标准和错误输出定向到文件。但请注意,您需要将它们发送到作业有权写入的地方。
【解决方案2】:

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

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

字符串 1 > 字符串 2
如果 STRING1 按字典顺序排在 STRING2 之后,则为真。

但是,在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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多