【问题标题】:When I exec a script with command "at", I get an infinite loop当我使用命令“at”执行脚本时,我得到一个无限循环
【发布时间】:2023-03-28 16:35:01
【问题描述】:

我正在学习 bash shell,我是初学者。
现在,我有一个名为 for_test 的脚本

#!/bin/bash
var1=3
until [ $var1 -eq 0 ]
do
    echo "Outer loop: $var1"
    var2=1
    while [ $var2 -lt 5 ]
    do
        var3=`echo "scale=4; $var1 / $var2" | bc`
    echo "    Inner loop:$var1 / $var2 = $var3"
    var2=$[ $var2 + 1 ]
    done
    var1=$[ $var1 - 1 ]
done >> temp.log.txt

当我在终端中执行它时,它运行良好。

Outer loop: 3
    Inner loop:3 / 1 = 3.0000
    Inner loop:3 / 2 = 1.5000
    Inner loop:3 / 3 = 1.0000
    Inner loop:3 / 4 = .7500
Outer loop: 2
    Inner loop:2 / 1 = 2.0000
    Inner loop:2 / 2 = 1.0000
    Inner loop:2 / 3 = .6666
    Inner loop:2 / 4 = .5000
Outer loop: 1
    Inner loop:1 / 1 = 1.0000
    Inner loop:1 / 2 = .5000
    Inner loop:1 / 3 = .3333
    Inner loop:1 / 4 = .2500

但是当我这样执行时:

at -f for_test 11:10

时间到了,脚本被执行,但我得到一个无限循环。
这是日志。

Outer loop: 3
    Inner loop:3 / 1 = 3.0000
    Inner loop:3 / 1 = 3.0000
    Inner loop:3 / 1 = 3.0000
    ……

我发现 $var2 总是等于 1。

我做错了什么?


我的 ubuntu 版本和 bash 版本。

$ uname -a
Linux android_su 2.6.35-32-generic #67-Ubuntu SMP Mon Mar 5 19:39:49 UTC 2012 x86_64 GNU/Linux


$ bash --version
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

@konsolebox
第二个命令工作正常。谢谢。
但是为什么第一个命令不起作用?我还是一头雾水。
第一条和第二条命令都是用 /bin/sh 执行的。

$ at -f for_test 14:16
warning: commands will be executed using /bin/sh
job 22 at Thu Aug 29 14:16:00 2013

$ echo "/bin/bash /home/android_su/android/source/linux_learned/for_test" | at 14:19
warning: commands will be executed using /bin/sh
job 23 at Thu Aug 29 14:19:00 2013

【问题讨论】:

  • 此代码适用于我的 atFedora 16
  • 第二个命令还是有警告的。它只是表明命令是通过 /bin/sh 解释的。但是你传递了一个调用/bin/bash /path/to/sh`的命令,所以at调用sh来读取命令/bin/bash ...然后/bin/bash被调用,参数为/path/to/sh,bash读取脚本。

标签: bash loops at-job


【解决方案1】:

当使用at -f 时,脚本中的命令会被解析就像您输入它们一样。这意味着#!/bin/bash 只是一个注释,不会导致您的脚本在bash 下执行。如果你没有使用-fat 会告诉你:

$ at 0900
warning: commands will be executed using /bin/sh

使用/bin/sh 的问题是真正的Bourne shell 不支持您使用的数学扩展,例如$[ 1 + 2 ]。这些是由ksh (afaik) 介绍的,现在在bash 中可用。有些人可能会使用他们的系统/bin/sh 得到不同的结果,因为并非所有系统都使用相同的sh。有些只使用bash,但还有更多类似Bourne 的变体,例如ash,可能是busybox 中的任何shell。

你只需要制作一个调用你的脚本的包装器(只是一个包含/path/to/script的文件)并使用那个文件作为at -f的输入

【讨论】:

  • @ruakh:$[ 1 + 2 ] 数学由ksh(原始来源,afaik)和bash 支持,但不是经典的sh。然而,不同的系统对sh 使用不同的 shell,有些系统比其他系统更原始(例如 ash
【解决方案2】:

尝试使用内部函数,因为 PATH 并不总是在 crontabs 中定义并且喜欢:

#!/bin/bash
var1=3
until (( var1 == 0 ))
do
    echo "Outer loop: $var1"
    var2=1
    while (( var2 < 5 ))
    do
        var3=$(echo "scale=4; $var1 / $var2" | bc)
        echo "    Inner loop:$var1 / $var2 = $var3"
        (( ++var2 ))
    done
    (( --var1 ))
done >> temp.log.txt

确保以 bash 的形式运行脚本,如下所示:

echo "/bin/bash /path/to/script.sh" | at 11:10

或者

at 11:10 <<EOF
/bin/bash /path/to/script.sh
EOF

【讨论】:

  • 还是不行。我得到一个无限输出“外循环:3”
  • @android_su 确保您使用 bash (/bin/bash) 而不是其他 shell 运行它。
  • @android_su 我做了一个更新,展示了一些使用 bash 显式运行它的示例。
  • 我认为第一行“#!/bin/bash”决定了我使用哪个shell,对吗?
  • @android_su 如果您通过另一个调度程序调用文件,有时您不能太依赖它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 2018-05-15
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多