Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 每秒执行一个命令,同时考虑命令运行所需的时间_Linux_Bash - Fatal编程技术网

Linux 每秒执行一个命令,同时考虑命令运行所需的时间

Linux 每秒执行一个命令,同时考虑命令运行所需的时间,linux,bash,Linux,Bash,我有一个脚本,它以%H:%M:%S格式读取时间,将其绘制在图像上,并将该图像设置为墙纸。而且效果很好: 现在,大约每五秒钟,脚本就会跳过一秒钟。我相信这是脚本完成工作所花费的时间,大约每五秒钟就累积到一秒钟。但我不知道如何修复它 下面是设置时间的循环: 而睡眠1;不要设置时钟;完成 下面是设置时钟功能: 摆钟{ 时钟时间=$date+“%H:%M:%S” 皈依\ -大小$monitor\u分辨率\ xc:$background\u color\ -字体$clock\u字体\ -填充$clock_

我有一个脚本,它以%H:%M:%S格式读取时间,将其绘制在图像上,并将该图像设置为墙纸。而且效果很好:

现在,大约每五秒钟,脚本就会跳过一秒钟。我相信这是脚本完成工作所花费的时间,大约每五秒钟就累积到一秒钟。但我不知道如何修复它

下面是设置时间的循环:

而睡眠1;不要设置时钟;完成 下面是设置时钟功能:

摆钟{ 时钟时间=$date+“%H:%M:%S” 皈依\ -大小$monitor\u分辨率\ xc:$background\u color\ -字体$clock\u字体\ -填充$clock_颜色\ -pointsize$时钟大小\ -重心\ -绘制文本0,0'$clock\u time'\ $config_dir/background.png feh-背景比例$config_dir/background.png } 我不认为这里需要所有的脚本,但是

我怎样才能解决这个问题?因此显示的时间是准确的。

创建一个名为delay的变量。调用set_clock后,使用date+%N获取当前纳秒。将延迟设置为1减去当前纳秒,并将循环更改为while sleep$delay,而不是while sleep 1

这样,您的循环将只休眠到下一秒的顶部


只有在图像的构建和显示时间始终少于一秒钟时,这才能解决问题。如果系统非常忙,并且您的过程需要一秒钟以上才能完成,它仍然会跳过一秒钟。

您需要一种跟踪开始时间的工具,并在重复之前计算正确的睡眠时间

您可以自己编写,但使用watch和-p/-precise参数更容易:

$ watch -n 1 -p 'sleep 0.5; date +%s.%N'
即使重复的命令休眠半秒,也不会延迟下一个命令;每次的毫秒数大致相同


嗯,不过它不能与shell函数一起工作,因为watch将在子进程中执行您的命令。您必须将整个命令扩展到watch参数中,这可能会给相对较长的命令带来不便。

使用主计时键,在后台运行set_clock,直到当前秒结束,如下所示:

!/usr/bin/env bash 摆钟{ printf-v时钟时间''%H:%M:%ST' 皈依\ -大小$monitor\u分辨率\ xc:$background\u color\ -字体$clock\u字体\ -填充$clock_颜色\ -pointsize$时钟大小\ -重心\ -绘制“文本”0,0'$clock\u time\ $config_dir/background.png feh-背景比例$config_dir/background.png } while:;做 在后台启动时钟更新 摆钟& 睡眠到当前秒结束 睡眠。$10**9-10$date+%N 如果背景子时钟仍在运行,请将其杀死! {kill-0$!&&kill$!;}2>/dev/null 完成
你可以这样做:

while sleep $(perl -MTime::HiRes=gettimeofday -E '$n=gettimeofday; say 1-($n-int($n))'); do
...
done
while slow_cmd; do
        perl -MTime::HiRes=gettimeofday,usleep -w -e '$n=gettimeofday; 
            usleep 1e6*(1-($n-int($n)))'
        update_status  # Quick cmd to report results of slow_cmd
done
请注意,您可能希望在完成需要时间的命令后进行睡眠。比如:

while sleep $(perl -MTime::HiRes=gettimeofday -E '$n=gettimeofday; say 1-($n-int($n))'); do
...
done
while slow_cmd; do
        perl -MTime::HiRes=gettimeofday,usleep -w -e '$n=gettimeofday; 
            usleep 1e6*(1-($n-int($n)))'
        update_status  # Quick cmd to report results of slow_cmd
done

您可以尝试使用date来获取高分辨率计时器,但我发现perl在实践中更具可移植性,也不那么令人惊讶。另外,请注意,出于同样的原因,我以第二种形式将睡眠推入了perl。也就是说,sleep通常不接受亚秒精度,但perl的usleep接受亚秒精度。

一个懒惰的解决方案是每秒只运行两次,改为使用sleep 0.5。@NateEldredge一个符合我心意的人!我们喜欢简单的解决方法:-这有什么意义?只需使用时钟小部件。或者只需在后台运行set_clock,这样它就不会计入1秒的迭代时间。@oguzismail不仅仅是时钟,我还计划在墙纸上添加更多内容。我没有使用任何桌面环境,我现在使用的是窗口管理器bspwm。我还没有发现任何像编写自己的脚本那样可以自定义的小部件。这是一个很好的解决方案,但是[-n$!]始终是正确的,因为$的值!在子对象终止时不会更改。最好使用另一种方法来测试孩子是否完成了,以避免向无意中的接收者发送信号。我真的很喜欢亚秒睡眠技巧,但仍然看不出使用信号的意义。睡觉时。。。;设置时钟并完成同样的事情,不是吗?@oguzismail是的,这里不需要使用信号^^