加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux – Shell脚本挂起,但只有在调用变量或strace时才会挂起

发布时间:2020-12-14 02:13:11 所属栏目:Linux 来源:网络整理
导读:一般问题:什么可能导致脚本本身工作正常,如果调用它的脚本或 shell(bash)命令将其调用为变量,则挂起? 换句话说,怎么会有一个脚本在这样调用时工作… / path / to / script arg arg …失败并在这样调用时挂起… VAR = $(/ path / to / script arg arg);? (
一般问题:什么可能导致脚本本身工作正常,如果调用它的脚本或 shell(bash)命令将其调用为变量,则挂起?

换句话说,怎么会有一个脚本在这样调用时工作… / path / to / script arg arg …失败并在这样调用时挂起… VAR = $(/ path / to / script arg arg);?

(主要编辑后注意到软件故障引起了很多初始测试,结果不正确)

我的具体情况:我有一个工作正常的脚本(启动,停止或重启java应用程序Apache Solr,adapted from here).代码如下,其命令是sbin / service solr [action],例如sbin / service solr start.

从脚本调用或直接从控制台调用(在我的情况下为bash),如sbin / service solr start,它工作正常并快速完成.但是,如果它被调用为变量,如VAR = $(sbin / service solr start);它可以工作,但会挂起futext / clock_gettime循环(下面的跟踪).如果它不是变量而是变成strace,它也会挂起.

奇怪的是,其他脚本以相同的方式使用相同的语法调用,例如sbin / service httpd start,调用变量时工作得很好.因此,当输出存储为变量时,显然可能存在一些脚本会使其挂起,但在不是这种情况时可以很好地运行.

这是测试挂起的内容和不挂起的内容的结果:

挂勾————————————————

> VAR = $(/ sbin / service solr start);
> VAR = $(source / sbin / service solr start);
> VAR = $(nohup / sbin / service solr start&);

(因此调用它的过程并不重要)此外,编辑脚本文件以使用源启动服务会导致服务无法正常工作.

不要挂————————————-

> VAR = $(/ sbin / service solr start>> / dev / null);

输出到/ dev / null允许我们请求输出而不会导致它挂起.然而,它并没有多大用处,因为没有收到实际的输出.

> / sbin / service solr start

与我最初的想法相反.这会输出一条简单的更新消息,理想情况下,我们会在变量和日志中捕获它 – 但尝试这样做会导致它挂起.

> VAR = $(/ sbin / service httpd restart);

挂起的语法在其他服务脚本上运行得很好,并且脚本的输出会毫无问题地传递给变量.

这是该脚本的完整代码:(注释已删除,自然$SOLR_DIR路径是真实脚本中的真实路径)

SOLR_DIR="[path/to/application]"
JAVA_OPTIONS="-Xms64m -Xmx64m -DSTOP.PORT=8079 -DSTOP.KEY=mustard -jar start.jar"
LOG_FILE="/var/log/solr.log"
JAVA="/usr/bin/java"

case $1 in
    start)
        echo "Starting Solr"
        cd $SOLR_DIR
        $JAVA $JAVA_OPTIONS 2> $LOG_FILE &
        ;;
    stop)
        echo "Stopping Solr"
        cd $SOLR_DIR
        $JAVA $JAVA_OPTIONS --stop
        ;;
    restart)
        $0 stop
        sleep 1
        $0 start
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}" >&2
        exit 1
        ;;
esac

var / log / solr.log中没有错误或任何异常(脚本中指定的日志文件). Centos Linux服务器,如果这是相关的.

在回答问题的早期版本时,@cdarke建议我在调用此脚本的脚本上运行strace -f -o strace.out / path / to / script,然后查看(海量!)输出文件strace.out.这是近3mbs,这里有一些观察:

>从大量活动开始,看起来脚本按预期运行.
>然后,日志文件的最后15%左右是这个,用不同的整数重复,但看似相同的十六进制代码:

25687 futex(0x688d454,FUTEX_WAIT_PRIVATE,1,{0,49980000}) = -1 ETIMEDOUT (Connection timed out)
25687 futex(0x688d428,FUTEX_WAKE_PRIVATE,1) = 0
25687 clock_gettime(CLOCK_MONOTONIC,{39074112,932735888}) = 0
25687 clock_gettime(CLOCK_REALTIME,{1355007234,333458000}) = 0

即使我在脚本仍在运行时这样做,这些PID在通过ps -p时也没有任何结果,而输出文件仍在变大,而这些代码行仍然被写入.我不太确定这是怎么回事.

这是输出进入永无止境的futex / clock_gettime循环之前的最后一位,在最后一部分显然是脚本正确执行之后(solr / solr.xml是一个Solr配置文件,需要读取才能开始) Solr过程):

25874 stat("solr/solr.xml",{st_mode=S_IFREG|0777,st_size=1320,...}) = 0
25874 write(2,"Dec 8,2012 5:12:05 PM org.apach"...,106) = 106
25874 socket(PF_INET,SOCK_STREAM,IPPROTO_IP) = 89
25874 fcntl(89,F_GETFL)                = 0x2 (flags O_RDWR)
25874 fcntl(89,F_SETFL,O_RDWR|O_NONBLOCK) = 0
25874 setsockopt(89,SOL_SOCKET,SO_REUSEADDR,[1],4) = 0
25874 bind(89,{sa_family=AF_INET,sin_port=htons(8983),sin_addr=inet_addr("0.0.0.0")},16) = 0
25874 listen(89,50)                    = 0
25874 setsockopt(89,4) = 0
25874 lseek(12,57747,SEEK_SET)        = 57747
25874 read(12,"PK34n10221Vi>F3472543643254002t002",30) = 30
25874 lseek(12,57827,SEEK_SET)        = 57827
25874 read(12,"225V377oSU24377334273256257_36l216m254262351224241]273255200314/5246c200"...,1237) = 1237
25874 futex(0x2aaab0173054,FUTEX_WAKE_OP_PRIVATE,0x2aaab0173050,{FUTEX_OP_SET,FUTEX_OP_CMP_GT,1} <unfinished ...>
25894 <... futex resumed> )             = 0
25894 futex(0x2aaab0173028,2,NULL <unfinished ...>
25874 <... futex resumed> )             = 1
25874 futex(0x2aaab0173028,1 <unfinished ...>
25894 <... futex resumed> )             = 0
25894 futex(0x2aaab0173028,1) = 0
25894 clock_gettime(CLOCK_REALTIME,{1355008325,376033000}) = 0
25894 futex(0x2aaab0173054,3,983000} <unfinished ...>
25874 <... futex resumed> )             = 1
25874 futex(0x2aaab0173054,1) = 0
25894 poll([{fd=89,events=POLLIN|POLLERR}],-1 <unfinished ...>
25874 <... futex resumed> )             = 1
25874 write(2,"2012-12-08 17:12:05.376:INFO::St"...,66) = 66
25874 write(2,"n",1)                 = 1
25874 mmap(0x41348000,12288,PROT_NONE,MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE,-1,0) = 0x41348000
25874 rt_sigprocmask(SIG_SETMASK,[],NULL,8) = 0
25874 sched_getaffinity(25874,32,{ ffff,0 }) = 32
25874 sched_getaffinity(25874,0 }) = 32
25874 gettid()                          = 25874
25874 rt_sigprocmask(SIG_BLOCK,8) = 0
25874 rt_sigprocmask(SIG_UNBLOCK,[HUP ILL BUS FPE SEGV USR2 TERM],8) = 0
25874 rt_sigprocmask(SIG_BLOCK,[QUIT],8) = 0
25874 mmap(0x41348000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,0) = 0x41348000
25874 mprotect(0x41348000,PROT_NONE) = 0
25874 futex(0x10632d54,NULL <unfinished ...>
25882 <... futex resumed> )             = -1 ETIMEDOUT (Connection timed out)
25882 futex(0x106cc428,1) = 0
25882 clock_gettime(CLOCK_MONOTONIC,{39075204,21489888}) = 0
25882 clock_gettime(CLOCK_REALTIME,422198000}) = 0
25882 futex(0x106cc454,49984000}) = -1 ETIMEDOUT (Connection timed out)
25882 futex(0x106cc428,72479888}) = 0
25882 clock_gettime(CLOCK_REALTIME,473185000}) = 0
25882 futex(0x106cc454,49987000}) = -1 ETIMEDOUT (Connection timed out)
25882 futex(0x106cc428,1) = 0

所以死亡螺旋之前的最后一行是通道12上的read().然后它只是循环futex和clock_gettime直到它被手动杀死.

最后一点可能无关紧要,但是,如果,similar to in this question,我运行使用nohup调用此脚本并将输出转移到/ dev / null的脚本,我在开始附近得到以下内容(大约100kb到输出文件中):一个巨大的数字这些:

25664 close(67)= -1 EBADF(错误的文件描述符)

他们从67,每次增加1,到:

25664 close(1023)= -1 EBADF(错误的文件描述符)

然后他们跟着

25664 open(“/ dev / null”,O_RDWR)= 3

同样,就我所见,PID是空的.不确定这是否相关 – 我想这开启了将nohup与输出一起使用到/ dev / null的可能性确实是对这类问题的一般修复,但我在某种程度上做错了,导致这些错误.

解决方法

我很确定问题是shell正在从/ sbin / service脚本和它启动的solr服务捕获输出,因此在继续之前会等待服务退出(或者至少关闭它的stdout).这是一个简单的演示:

$bg_service() { while true; do sleep 10; done; }
$start_bg_service() { echo "starting"; bg_service& echo "running"; }
$start_bg_service 
starting
[1] 8656
running
$var=$(start_bg_service)
[It hangs at this point... until I open another shell and kill the background process]

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读