1

我在这样的 bash 脚本中有一个小函数,

func()
{
    
    local nice_val="$NICE -n -19"
    
    /* bunch of if/else statements and some loops*/
    
    $nice_val $NOHUP a.out >> $log_file 2>&1 &
}

当我尝试执行这个文件时,我看到了这个错误。/root/bringup.sh:第 323 行:/usr/bin/nice -n -19:没有这样的文件或目录

以下是我验证的几件事,

  1. 是的,不错的可执行文件在 /usr/bin/nice 中退出
  2. 我的 $PATH 还包含 /usr/bin/
  3. 检查我是否缺少任何库,我不认为我是。
root@dg:~# ldd /usr/bin/nice
        linux-vdso.so.1 (0x00007ffdc4dab000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f749b9bf000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f749bf67000)
root@dg:~# find / -name libc.so.6
/lib/x86_64-linux-gnu/libc.so.6

注意:1.我以 root 和 $NICE 身份运行所有内容,$NOHUP 是在脚本开头获取源(使用“源”)的一些 shell 变量。2.这个脚本被另一个脚本调用 3.我在网上阅读了清除哈希(hash -r)如果我的“nice”被移动但没有帮助可能会有所帮助。4. 所有这些脚本都在一个容器内运行。但我想这应该不会影响任何事情。

在上面的代码片段中,如果我将 $nice_val 替换为“nice”的完整路径,它就可以工作。ie /usr/bin/nice -n -19 $NOHUP a.out >> $log_file 2>&1 &---> 令人惊讶的是,这行得通。哦,我检查了我是否有任何额外的空格,/r's。我没有看到任何这些。

我真的无法理解出了什么问题。非常感谢您对此问题的任何见解。非常感谢。

更新:这是我的代码的问题:(这是重现问题的浓缩虚拟代码)文件 1:bringup.sh

#! /bin/bash

declare -r NOHUP="/usr/bin/nohup"
declare -r NICE="/usr/bin/nice"
declare -r CAT="/bin/cat"

log_file="/root/affinity/dumplog"
values_file="/root/affinity/values"
niceval="$NICE -n -10"

get_indexed_val()
{
    local val=$1
    if [ -e $values_file ]; then
        local val_str=$($CAT $values_file)
        IFS=','
        read -ra cpu_array <<< "$val_str"
        #
        # If you uncomment the below line(setting back the IFS to 'space', code works fine.
        #
        #IFS=' '
        return ${cpu_array[$val]}
    fi
    return 0
}

index=0
for (( index=0; index < 4; index++ )); do
    get_indexed_val $index
    myval=$?
    $niceval $NOHUP /root/affinity/loop.sh $myval >> $log_file 2>&1 &
done

文件 2:loop.sh

#! /bin/bash

i=0
number=$1
while [ $i -lt $number  ]; do
        sleep 0.1
done

文件 3:价值观

140,150,160,170

如果您不重置 IFS,您将看到的错误消息。

./bringup.sh: line 28: /usr/bin/nice -n -10: No such file or directory
./bringup.sh: line 28: /usr/bin/nice -n -10: No such file or directory
./bringup.sh: line 28: /usr/bin/nice -n -10: No such file or directory
./bringup.sh: line 28: /usr/bin/nice -n -10: No such file or directory

谢谢你们。非常感激。

4

1 回答 1

4

您收到的错误消息/root/bringup.sh: line 323: /usr/bin/nice -n -19: No such file or directory, 表明 " -n -19" 被视为文件名的一部分,而不是作为参数。nice -n -19由于/usr/bin 目录中没有名为 " " 的文件,因此您会收到文件未找到错误。

通常,当您扩展包含空格(或其他空格)并且周围没有双引号的变量时,变量的值将根据空格拆分为“单词”。在这种情况下,我希望它被分成“ /usr/bin/nice”、“ -n”和“ -19”,因此第一个将被视为要运行的命令/文件名,而其他则被视为参数。但在这种情况下,分裂显然没有发生。我看到了几种可能的解释:

  • IFS已经变了。该IFS变量定义了哪些字符被视为用于分词目的的空格;如果它不包含空格字符,那就可以解释为什么该值没有正常拆分。

    更改IFS可能会产生很多类似这样的奇怪效果,因此如果您出于某种原因需要更改它,最好在之后尽快将其恢复正常。

    通过将设置设置为该命令的前缀,有时也足以将IFS更改仅应用于单个命令。例如:

     IFS=, read -r field1 field2 field3
    

    将以逗号分隔字段,但由于该IFS设置专门适用于该命令,因此无需在之后将其设置回来。但这并不总是符合您的预期,因为该设置适用于该命令的执行,而不适用于其参数的解析方式。例如,IFS=, echo $var$varon normal whitespace的值拆分,然后设置IFSwhileecho打印结果(所以设置没有实际效果)。

  • 字符串中的那些字符可能不是普通的空格,而是一些看起来相似但不同的东西,比如不间断的空格。您可以通过对文本进行十六进制转储来检查。这是一个例子(我添加了^^s):

     $ echo "/usr/bin/nice -n -19" | xxd    # These are normal spaces
     00000000: 2f75 7372 2f62 696e 2f6e 6963 6520 2d6e  /usr/bin/nice -n
                                               ^^                    ^
     00000010: 202d 3139 0a                              -19.
               ^^                                       ^
     $ echo "/usr/bin/nice -n -19" | xxd    # These are non-breaking spaces
     00000000: 2f75 7372 2f62 696e 2f6e 6963 65c2 a02d  /usr/bin/nice..-
                                               ^^ ^^                 ^^
     00000010: 6ec2 a02d 3139 0a                        n..-19.
                 ^^ ^^                                   ^^
    

    看看第二个转储如何在十六进制中使用“c2 a0”而不是“20”,以及右侧文本中的“..”而不是“”?这些是 UTF-8 编码中的不间断空格。试着echo "$nice_val" | xxd输入你的脚本,看看它打印了什么。

  • 该脚本在 zsh(而不是 bash)下运行。默认情况下,zsh 不进行分词(因为它实际上会导致很多错误,并且通常有更好的方法来完成所需的操作)。

  • 您实际上在变量引用周围有双引号,只是没有将它们包含在问题中。如果这是实际命令:

     "$nice_val" $NOHUP a.out >> $log_file 2>&1 &
    

    ...那么错误消息将非常有意义。请注意,通常,在变量引用周围加上双引号是一个好主意(以避免文件名通配可能导致的分词问题),但在这种情况下,您指望它。

    但是无论如何将命令存储在这样的变量中有些不可靠(请参阅BashFAQ #50:我试图将命令放入变量中,但复杂的情况总是失败!)。为您的NICENOHUP“命令”定义函数而不是变量可能会更好。像这样的东西:

     nice_val() {
         /usr/bin/nice -n -19 "$@"
     }
    
于 2020-10-03T16:54:02.223 回答