V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
different
V2EX  ›  Linux

关于 shell 下的 sleep 问题

  •  
  •   different · 2019-06-01 14:15:49 +08:00 · 4510 次点击
    这是一个创建于 2002 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近遇到下面这个问题,可能表达的不是很清楚。。 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..............."

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

    第 1 条附言  ·  2019-06-01 22:28:43 +08:00
    最新修改:
    请问下面两段代码有什么不一样的:
    代码一:
    #以行读取
    oldIFS=$IFS;
    IFS=$'\n';
    for line in $(cat tasklist.txt )
    do
    echo $line
    nohup mpirun -np 1 ./bin/ASDMPI cff &
    sleep 1
    done
    kill -9 $(pgrep ASDMPI)

    以上代码输出
    1
    nohup: appending output to 'nohup.out'
    2
    nohup: appending output to 'nohup.out'
    3
    nohup: appending output to 'nohup.out'




    代码二:

    cat tasklist.txt | while read line
    do
    echo $line
    nohup mpirun -np 1 ./bin/ASDMPI cff &
    sleep 1
    done
    kill -9 $(pgrep ASDMPI)


    以上代码输出
    1
    nohup: appending output to 'nohup.out'


    测试环境为:Ubuntu18.04
    31 条回复    2019-06-03 16:13:19 +08:00
    guog
        1
    guog  
       2019-06-01 15:15:55 +08:00 via Android
    贴下两台电脑的操作系统型号及版本呗,这让人怎么猜
    omph
        2
    omph  
       2019-06-01 15:19:36 +08:00
    看看是不是换行符的问题
    PTLin
        3
    PTLin  
       2019-06-01 19:14:07 +08:00
    wait 一下
    different
        4
    different  
    OP
       2019-06-01 20:05:07 +08:00
    @guog
    @omph
    Ubuntu18.04 不行
    centos6.4 没问题
    至于换行符,应该不是这个问题。我之前在多台服务器上测试没问题的,然后今天直接拷贝在我电脑上跑就出问题了
    different
        5
    different  
    OP
       2019-06-01 20:13:50 +08:00
    @PTLin wait 的话就“卡住了”鸭,等一条条指令执行完(可我的那个程序要执行几个小时的,,,)
    Kobayashi
        6
    Kobayashi  
       2019-06-01 20:17:49 +08:00 via Android
    set -x
    ys0290
        7
    ys0290  
       2019-06-01 20:18:56 +08:00 via iPhone
    有什么问题?好像也没说
    different
        8
    different  
    OP
       2019-06-01 20:35:03 +08:00
    @Kobayashi 我不是很懂,我对 shell 不是很理解,抱歉,可以详细说说看吗?感谢
    different
        9
    different  
    OP
       2019-06-01 20:35:53 +08:00
    @ys0290 第一个代码比第二个代码多出了
    sleep 1
    这一行。
    但是执行结果就不一样了。
    前者循环了一次,后者循环了 3 次
    lionseun
        10
    lionseun  
       2019-06-01 21:03:24 +08:00
    使用"{}"包裹 wihle 循环
    wikinee
        11
    wikinee  
       2019-06-01 21:21:39 +08:00
    楼主这脚本好怪啊,我怎么就打印两行就不出了,参考网上的提示,改成这样:

    #!/bin/bash
    while read -r line || [[ -n ${line} ]]
    do
    echo "$line, do something"
    sleep 1
    done < tasklist.txt
    echo "end..............."
    different
        12
    different  
    OP
       2019-06-01 22:09:28 +08:00
    @wikinee 你机器上面不应该输出两行吧。
    我把你的代码放在我的机器上测试有问题
    while read -r line || [[ -n ${line} ]]
    do
    echo $lines
    mpirun -np 1 ./bin/ASDMPI cff &
    sleep 2
    done<tasklist.txt

    症状:
    只打印一次
    调试:
    只要把 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`
    done<tasklist.txt
    for task in ${my_array[*]}
    do
    echo "exc"
    nohup mpirun -np 1 ./bin/ASDMPI cff &
    sleep 1
    done
    echo "end..............."

    但是我觉得本质和你的代码应该是一致的,可是结果却不一样。!!!!(也就是说,我用 for 循环就没问题)
    不知道我说清楚没。。?
    wikinee
        13
    wikinee  
       2019-06-02 08:08:50 +08:00
    @different 输出两行的原因是最后一行无法读取,所以才加了 [[ -z ${line} ]] 判断,我测试的 tasklist.txt 也就三行最后没有空行,while 读不到最后一行这问题很典型
    另外,我也不知道你的 nohub xxxx 是什么命令,大概就是能持续输出结果的吧,我这边用 ping www.baidu.com 代替:

    #!/bin/bash
    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,其他系统不是。。。
    wikinee
        14
    wikinee  
       2019-06-02 08:15:36 +08:00
    我自己写 shell 脚本也是百度编程法,遇到问题就去查[捂脸]
    后来我发现一个叫 shellcheck 的神器,类似 Python 的 pylint 或者 其他语言的 hint 那种,
    能提示你脚本哪里不合适,语法检查等等,安装之后还可以配置编辑器插件使用
    像 vscode 的 shellcheck 插件
    different
        15
    different  
    OP
       2019-06-02 09:00:08 +08:00
    @wikinee 比较郁闷的是:
    我的
    nohup mpirun -np 1 ./bin/ASDMPI cff &
    这一行,如果用其他命令代替就不会有问题。。(可能我这一行代码的 ASDMPI 程序有错?但是我却能单独执行)
    说白了就是
    nohup mpirun -np 1 ./bin/ASDMPI cff &
    和 sleep 1
    不能同时存在。
    如果你用其他程序代替我的 ASDMPI 去测试,可能观察不到错误
    wikinee
        16
    wikinee  
       2019-06-02 09:15:13 +08:00
    nohup mpirun -np 1 ./bin/ASDMPI cff & 改成:
    nohup mpirun -np 1 ./bin/ASDMPI cff > /dev/null 2>&1 &

    另外就怕命令自带阻塞。。。
    Kobayashi
        17
    Kobayashi  
       2019-06-02 09:30:36 +08:00
    我是头一次听说不知道 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
    Kobayashi
        18
    Kobayashi  
       2019-06-02 09:42:44 +08:00
    for in 循环文件内容(仅限循环文件)属于山炮用法,谁用坑死谁。

    Why you don't read lines with "for",http://mywiki.wooledge.org/DontReadLinesWithFor

    我今天可能嘴巴比较臭,想说点大实话(一点建议)。有问题 Google,Stack Overflow,在一个灌水论坛提问技术是多么想不开?
    HEROic
        19
    HEROic  
       2019-06-02 09:43:41 +08:00 via Android
    @Kobayashi 出现大佬
    ps:循环真的要注意空白行!
    different
        20
    different  
    OP
       2019-06-02 10:05:33 +08:00
    @wikinee 我之前的命令就是你这个,后来我以为是我的命令问题,我就去掉了后面的> /dev/null 2>&1。。。
    different
        21
    different  
    OP
       2019-06-02 10:13:32 +08:00
    @Kobayashi 啊哈,感谢感谢,还有个疑问,如果 ASDMPI 这个程序能吃掉 stdin 的内容,为何这种问题只存在某些 Linux 发行版里面?我的 Ubuntu18.04 有问题,centos6.4 没问题,。。
    Kobayashi
        22
    Kobayashi  
       2019-06-02 10:29:00 +08:00
    @different 你两次贴的内容并不一样,后者没有 sleep 1。while read 可能和 ASDMPI 程序存在资源竞争,在外层循环语句 sleep 时,标准输入 stdin 被 ASDMPI 拿了?目前只能这样推测。
    ps1aniuge
        23
    ps1aniuge  
       2019-06-02 12:37:04 +08:00
    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,字符串命令的身影。
    qinghon
        24
    qinghon  
       2019-06-02 16:08:09 +08:00 via Android
    @ps1aniuge 气泵射钉枪至今没有取代锤子的地位
    面向对象的 c++至今没有取代面向函数的 c 的地位
    different
        25
    different  
    OP
       2019-06-02 17:27:26 +08:00
    @Kobayashi
    一开始贴的内容有点乱。。。
    单纯看附言里面的内容的话,
    附言里面的两份代码均有 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'

    而我的机器并不是。
    Kobayashi
        26
    Kobayashi  
       2019-06-03 07:49:04 +08:00 via Android
    @different 这我就说不清了,无能为力。
    different
        27
    different  
    OP
       2019-06-03 12:17:11 +08:00
    @Kobayashi 没事,已经非常感谢了。
    james122333
        28
    james122333  
       2019-06-03 15:20:40 +08:00
    #!/bin/bash
    while read -r line
    do
    echo $line
    (mpirun -np 1 ~/bin/test &) &
    sleep 1
    done < tasklist.txt
    wait
    echo "end..............."
    james122333
        29
    james122333  
       2019-06-03 15:26:10 +08:00
    打错
    james122333
        30
    james122333  
       2019-06-03 15:31:25 +08:00
    #!/bin/bash
    while read -r line
    do
    echo $line
    (mpirun -np 1 ~/bin/test & wait) &
    sleep 1
    done < tasklist.txt
    wait
    echo "end..............."
    james122333
        31
    james122333  
       2019-06-03 16:13:19 +08:00
    或者 mpirun 加上一个参数--stdin none
    会导向 stdin 的程序 有点恶心 不太好用
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2536 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 15:40 · PVG 23:40 · LAX 07:40 · JFK 10:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.