【问题标题】:bash: return code from redirected input commandbash:从重定向的输入命令返回代码
【发布时间】:2015-10-19 03:51:21
【问题描述】:

我有一个 bash 脚本,用于循环和处理类似 SQL 查询的结果。

while read field1 field2 field3 field4
do
    {...something here...}
done < <(mysql -h $HOST -u $USER -p"$PASS" $DB << EOF
 {...multi-line select query here...}
EOF)

我不知道如何解决的问题是如何重构它,以便在查询数据库出现问题时获取返回码、错误并跳过循环?

编辑:

我已尝试使用具有以下内容的命名管道。

mkfifo /tmp/mypipe
mysql -h $HOST -u $USER -p"$PASS" $DB << EOF >> /tmp/mypipe
  {...multi-line select query here...}
EOF
echo $?
{...loop here...}

这似乎不起作用,因为 mysql 命令会等待管道被读取,然后再继续。所以除非我有东西读取管道mysql不会退出有返回码。

我已尝试先将查询结果存储到一个变量中,如下所示。

DATADUMP=$(mysql -h $HOST -u $USER -p"$PASS" $DB -e \
  'select stuff from place \
  join table 1 on record ..... \
  ')

我遇到的问题是读取循环只会从 DATADUMP 变量中读取前四个“单词”,而忽略其余的。

在这一点上,除非有人回来有一个好主意,否则我将 mktemp 一个临时文件来保存查询结果。我希望避免不断地读写磁盘,但我的最后期限很快就要到了。

【问题讨论】:

  • mysql 失败时,你会得到循环看到的任何输出吗?那就是您只对循环从不运行的情况感兴趣吗?或者您可以获得部分数据但仍然需要捕获命令失败?如果是后者(或者您特别想要返回代码而不仅仅是“失败”),那么您可能需要使用 fifo,以便您可以单独运行 mysql 并写入它,然后稍后再读取它(或类似的东西)。
  • 我会说,仅仅“跳过”可能还不够。只要一致性很重要并且与 DDL 无关,就可以进行事务。此外,bash 可能不是最好的选择。比如:将查询合并到文件中(如果可能的话,使用事务处理)然后执行。
  • 当mysql失败时,无论它的输出是什么,都会被循环处理。

标签: mysql bash io-redirection return-code


【解决方案1】:

除了在处理之前捕获mysql 命令的整个输出之外,没有其他方便的方法可以做到这一点。如果您认为它不会是千兆字节的数据,您可以将其捕获到一个变量中,或者捕获到一个临时文件中。只有这样才能保证在出错的情况下不处理任何部分结果。

如果您知道所有错误都会产生空输出,那么这将相当简单,因为 while 循环根本不会执行。您将无法区分错误和空搜索,但您可以通过生成错误指示来解决此问题:

got_data=0
while read field1 field2; do
  got_data=1
  # ...
done < <( mysql ... || printf "%s %d" "ERROR" $?) <<EOF
  # ...
EOF
)
if ((!got_data)); then
  if [[ $field1 == "ERROR" ]]; then
    # error code is in $field2
  else
    # query returned no result
fi

但是,前提很可能是错误的。特别是,查询返回中间的网络故障可能会同时产生一些输出和错误指示。在这种情况下,上面的代码会处理部分返回。

如果您实际上不介意处理部分结果,只要最终检测到错误,那么您可以对上述代码使用一个简单的变体。该代码保证mysql 的不成功退出最终将产生以ERROR 标记开头的行。 (我不知道mysql是否保证在网络传输中断的情况下输出一个尾随换行符。你需要玩一些游戏来保证printf输出的错误行总是单独出现在一行上。 )

上面有一个小技巧:错误行(例如ERROR 3)以printf 输出没有尾随的换行符。缺少尾随换行符将导致read 以失败代码退出,即使它将成功地将行拆分为变量field1field2。这使得在while 循环内尝试将错误指示与正常数据区分开来是不必要的,尽管在while 循环之后仍然需要明确的测试指示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多