技术解析

关于 shell 下的 sleep 问题
0
2021-06-21 03:34:33
idczone

最近遇到下面这个问题,可能表达的不是很清楚。。 tasklist.txt 文件里面就只有三行

1

2

3

下面代码输出

1

(只循环了一次)

#! /bin/bash

cat tasklist.txt | while read lines

do

echo $lines

cd /media/ice/0A9AD66165F33762/magnet_data/2019/修改 alpha/changeAlpha/runInMyComputer/80K/alpha0.01/50fs/80_1200

mpirun -np 1 ./bin/ASDMPI cff &

sleep 1

done

echo "end..............."

下面代码输出

1

2

3

(循环了三次)

#! /bin/bash

cat tasklist.txt | while read lines

do

echo $lines

cd /media/ice/0A9AD66165F33762/magnet_data/2019/修改 alpha/changeAlpha/runInMyComputer/80K/alpha0.01/50fs/80_1200

mpirun -np 1 ./bin/ASDMPI cff &

done

echo "end..............."

在我的电脑下有问题,在另一台电脑下没问题,奇怪了 这是何解??郁闷了


贴下两台电脑的操作系统型号及版本呗,这让人怎么猜

看看是不是换行符的问题

wait 一下



Ubuntu18.04 不行
centos6.4 没问题
至于换行符,应该不是这个问题。我之前在多台服务器上测试没问题的,然后今天直接拷贝在我电脑上跑就出问题了

wait 的话就“卡住了”鸭,等一条条指令执行完(可我的那个程序要执行几个小时的,,,)

set -x

有什么问题?好像也没说

我不是很懂,我对 shell 不是很理解,抱歉,可以详细说说看吗?感谢

第一个代码比第二个代码多出了
sleep 1
这一行。
但是执行结果就不一样了。
前者循环了一次,后者循环了 3 次

使用"{}"包裹 wihle 循环

楼主这脚本好怪啊,我怎么就打印两行就不出了,参考网上的提示,改成这样:
/>while read -r line || [[ -n ${line} ]]
do
echo "$line, do something"
sleep 1
done < tasklist.txt
echo "end..............."

你机器上面不应该输出两行吧。
我把你的代码放在我的机器上测试有问题
while read -r line || [[ -n ${line} ]]
do
echo $lines
mpirun -np 1 ./bin/ASDMPI cff &
sleep 2
done症状:
只打印一次
调试:
只要把 mpirun -np 1 ./bin/ASDMPI cff &
或者 sleep 2 这两行代码的其中一行去掉就能打印 3 次。
这是何解?

目前我的解决方案是:
i=0
declare -a my_array
while read lines
do
my_array[$i]=$lines
i=`expr $i + 1`
donefor task in ${my_array[*]}
do
echo "exc"
nohup mpirun -np 1 ./bin/ASDMPI cff &
sleep 1
done
echo "end..............."
但是我觉得本质和你的代码应该是一致的,可是结果却不一样。!!!!(也就是说,我用 for 循环就没问题)
不知道我说清楚没。。?

输出两行的原因是最后一行无法读取,所以才加了 [[ -z ${line} ]] 判断,我测试的 tasklist.txt 也就三行最后没有空行,while 读不到最后一行这问题很典型
另外,我也不知道你的 nohub xxxx 是什么命令,大概就是能持续输出结果的吧,我这边用 ping www.baidu.com 代替:
/>while read -r line || [[ -n ${line} ]]
do
echo "$line"
将日志重定向,将标准错误输出重定向到标准输出
ping www.baidu.com > /dev/null 2>&1 &
sleep 1
done < tasklist.txt
echo "end..............."
另外,楼主执行的时候,要么把文件加可执行权限,直接 ./xxx.sh 要么 bash xxx.sh
不要 sh xxx.sh ,因为 Debian 或者 Ubuntu 默认 shell 是 dash,其他系统不是。。。

我自己写 shell 脚本也是百度编程法,遇到问题就去查[捂脸]
后来我发现一个叫 shellcheck 的神器,类似 Python 的 pylint 或者 其他语言的 hint 那种,
能提示你脚本哪里不合适,语法检查等等,安装之后还可以配置编辑器插件使用
像 vscode 的 shellcheck 插件

比较郁闷的是:
我的
nohup mpirun -np 1 ./bin/ASDMPI cff &
这一行,如果用其他命令代替就不会有问题。。(可能我这一行代码的 ASDMPI 程序有错?但是我却能单独执行)
说白了就是
nohup mpirun -np 1 ./bin/ASDMPI cff &
和 sleep 1
不能同时存在。
如果你用其他程序代替我的 ASDMPI 去测试,可能观察不到错误

nohup mpirun -np 1 ./bin/ASDMPI cff & 改成:
nohup mpirun -np 1 ./bin/ASDMPI cff > /dev/null 2>&1 &
另外就怕命令自带阻塞。。。

我是头一次听说不知道 set -x 是 debug,而且也不搜索的。不过鉴于你这问题比较特殊,还是来解释一下。
问题在于 while read 循环每次从 stdin 读取内容,而你的后台命令 ASDMPI 不怎么厚道,趁你 sleep 1 时把 stdin 的内容给吃了。
解决方案,方案 1,关闭后台命令的标准输入;方案 2,先把 tasklist.txt 内容逐行读入 array,for 循环 array。
https://pastebin.com/Jz2sqvck
另外,有时间好好学学 bash 是非常重要的。你第一条附言里 for line in $(cat tasklist.txt)存在空白格问题,这种问题往大了说,能把你搞得只能跑路。https://wiki.bash-hackers.org/scripting/tutoriallist

for in 循环文件内容(仅限循环文件)属于山炮用法,谁用坑死谁。
Why you don't read lines with "for",http://mywiki.wooledge.org/DontReadLinesWithFor
我今天可能嘴巴比较臭,想说点大实话(一点建议)。有问题 Google,Stack Overflow,在一个灌水论坛提问技术是多么想不开?

出现大佬
ps:循环真的要注意空白行!

我之前的命令就是你这个,后来我以为是我的命令问题,我就去掉了后面的> /dev/null 2>&1。。。

啊哈,感谢感谢,还有个疑问,如果 ASDMPI 这个程序能吃掉 stdin 的内容,为何这种问题只存在某些 Linux 发行版里面?我的 Ubuntu18.04 有问题,centos6.4 没问题,。。

你两次贴的内容并不一样,后者没有 sleep 1。while read 可能和 ASDMPI 程序存在资源竞争,在外层循环语句 sleep 时,标准输入 stdin 被 ASDMPI 拿了?目前只能这样推测。

shell 坑太多,一条 sleep 就把 shell 打 懵逼了!
bash 已死,powershell 是脚本人的未来。
请让我安利下 linux 版 powershell,谢谢:
问:powershell 啥时候开源(+免费)的?
答:
2015 年小范围内部开源,2016 年开发者大会上,正式法律开源。

问:开源后的 powershell,属于谁的财产?
答:
在遵守其开源协议的前提下。powershell 开源后。属于 [社区财产] 或 [任何人财产] 。

问:谁是 powershell 开源免费的最大受益者?
答:
powershell 可以运行在,win,mac,ubuntu1404+,centos7,debian8+,suse12+,arch,alpine linux,树莓派 Raspbian,win10-iot,docker,snap-app,open-wrt 路由器等。
这些系统使用者,是 powershell 开源免费的最大受益者。

问:powershell 完全开源了么?
答:
不完全是。
1 powershell 之所以简单、强大、好用。靠的是 powershell5.1+win 自带的 powershell 库。我们应该主要使用这些库。
这些库,并没有开源。开源之前,是否免费我也不清楚。
2 powershell6,powershell7,和相关的库,开源了。
这里面的区别主要是 [win 自带软件,相关的 powershell 库] 。
库数量很多,如 iis 的 ps 库。但这些 win 独有软件的 ps 库,跨不了平台。即便开源给 liux 也并没啥用。
另外一些 win,linux 通用的 ps 库,比如 sqlserver 的 powershell 库,已经开源免费放在了 github 和 powershell 画廊。

问:如何看待 bash,及 linux shell 脚本将来的地位,命运?
问:powershell 在 linux 中的前景如何?
答:
就好像 [气泵射钉枪] 必将取代 [锤子] 一样,先进生产力必然代替落后的。
就好像面向对象的 powershell,必然取代面向字符的 bat 那样。
powershell 发展成熟后。以 bat,bash 为代表的,上一代面向字符串的脚本语言,面向字符串的命令,难免被边缘化。
过几年后,开机启动脚本,特简单的脚本中,或许还残留有 bat,bash,字符串命令的身影。

气泵射钉枪至今没有取代锤子的地位
面向对象的 c++至今没有取代面向函数的 c 的地位


一开始贴的内容有点乱。。。
单纯看附言里面的内容的话,
附言里面的两份代码均有 sleep
但是在另一台机器( centos 6.4 )上测试
均输出
1
nohup: appending output to 'nohup.out'
2
nohup: appending output to 'nohup.out'
3
nohup: appending output to 'nohup.out'
而我的机器并不是。

这我就说不清了,无能为力。

没事,已经非常感谢了。

/>while read -r line
do
echo $line
(mpirun -np 1 ~/bin/test &) &
sleep 1
done < tasklist.txt
wait
echo "end..............."

打错

/>while read -r line
do
echo $line
(mpirun -np 1 ~/bin/test & wait) &
sleep 1
done < tasklist.txt
wait
echo "end..............."

或者 mpirun 加上一个参数--stdin none
会导向 stdin 的程序 有点恶心 不太好用

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服