微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

并发登录bash脚本

我目前正试图弄清楚为什么 shell脚本在每次偶尔记录时都会失败.

我有一个shell函数,如下所示:

log()
{
   local l_text=$1
   local l_file="/path/to/logs/$(date +%Y%m%d)_script.log"

   local l_line="$(date +'%Y-%m-%d %H:%M:%s') $(hostname -s) ${l_text}"

   echo ${l_line} >> ${l_file}
}

现在每隔一段时间就会因语法错误而失败:

/path/to/script.sh: command substitution: line 163: Syntax error near unexpected token `)'
/path/to/script.sh: command substitution: line 163: `hostname -s) ${l_text}'

问题是,我有多个子流程,每个子流程都需要记录以及发送陷阱(在此期间也会执行记录).我调试了这个问题并发现,当这个函数同时输入三次时会发生这种情况.首先是主要过程,然后是孩子.在执行l_text的日期部分之后,main get被一个由child引起的陷阱中断,并且在此陷阱中尝试记录某些内容.子进程和陷阱很好地完成了日志记录,但是然后main在陷阱之后恢复并尝试执行主机名部分(假定为)并因此错误而失败.

因此,似乎主要不喜欢在产生$(日期’%Y-%m-%d%H:%M:%S’)$(主机名-s)${l_text}部分时被置于睡眠状态日志语句并不能很好地恢复.我假设这应该工作正常,因为我只是使用局部变量和线程安全输出方法.

这是我遇到的一般并发问题吗?或者这是否特别针对bash脚本中的陷阱机制?我知道C中SIGNAL处理的商品,所以我知道SIGNAL处理程序中只允许某些操作.但是,我不知道在bash脚本中处理SIGNAL时是否也适用相同的预防措施.我试图找到关于此的文档,但是我找不到的任何文档都没有给出脚本中SIGNAL处理问题的任何迹象.

编辑:

这是一个可用于复制问题的实际简单脚本:

#!/bin/bash

log() {
  local text="$(date +'%Y-%m-%d %H:%M:%s') $(hostname -s) $1"
  echo $text >> /dev/null
}

sub_process() {
  while true; do
    log "Thread is running"
    kill -ALRM $$
    sleep 1
  done
}

trap "log 'received ALRM'" ALRM 

sub_process &
sub_process_pid=$!
trap "kill ${sub_process_pid}; exit 0" INT TERM


while true; do
  log "Main is running"
  sleep 1
done

由于第5行中的语法错误,此脚本每隔一段时间就会被杀死.第5行是echo $text>> / dev / null,但由于语法错误也提到了hostname命令,类似于我上面发布的那个,我假设还有一个一个错误,实际错误在第4行,这是本地的text =“$(日期’%Y-%m-%d%H:%M:%S’)$(主机名-s)$1”.

有谁知道如何处理上面的脚本来纠正它?我已经尝试将字符串的构造移出一些临时变量:

log() {
  local thedate=$(date +'%Y-%m-%d %H:%M:%s')
  local thehostname=$(hostname -s)
  local text="${thedate} ${thehostname} $1"
  echo $text >> /dev/null
}

这种方式错误出现频率较低,但仍然存在,因此这不是一个真正的修复.

解决方法

我会说这绝对是bash中的一个错误,我鼓励你向bash开发者报告.至少,你应该永远不会得到语法错误的语法错误代码.

为了记录,我得到了与GNU bash版本4.2.10(1)-release(x86_64-pc-linux-gnu)相同的结果.

我发现你可以通过不在陷阱处理程序中调用函数解决问题.例如.更换

trap "log 'received ALRM'" ALRM

trap "echo $(date +'%Y-%m-%d %H:%M:%s') $(hostname -s) received ALRM" ALRM

让我的脚本稳定.

I kNow about the commodities of SIGNAL handling in C,so I am aware
that only certain operations are allowed in SIGNAL handlers. However I
am not aware if the same precautions also apply when handling SIGNALs
in a bash script.

我想你不应该采取特别的预防措施,但显然你在实践中.鉴于问题似乎在没有函数调用的情况下消失了,我猜测bash中的某些东西或者不是重入的,它应该是或者在第一时间阻止重新进入.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐