Linux sh 脚本抛出“#!/bin/sh: not found”

Noj*_*741 7 linux bash sh ubuntu

我有一个脚本

#!/bin/sh

# Automatically remove a torrent and delete its data after a specified period of
# time (in seconds).

TARGET=/var/www/transmission/completed
USER=name
PASS=pass
BIN="/usr/bin/transmission-remote"

# The default is 5 minutes (in seconds).
CUTOFF=`expr 100 \* 3`

##############################################
### You shouldn't need to edit below here. ###
##############################################

# Tokenise over newlines instead of spaces.
OLDIFS=$IFS
IFS="
"

for ENTRY in `$BIN -n $USER:$PASS -l | grep 100%.*Done.*Finished`; do

    # Pull the ID out of the listing.
    ID=`echo $ENTRY | sed "s/^ *//g" | sed "s/ *100%.*//g"`

    # Determine the name of the downloaded file/folder.
    NAME=`$BIN -n $USER:$PASS -t $ID -f | head -1 |\
         sed "s/ ([0-9]\+ files)://g"`

    # If it's a folder, find the last modified file and its modification time.
    if [ -d "$TARGET/$NAME" ]; then
        LASTMODIFIED=0
        for FILE in `find $TARGET/$NAME`; do
             AGE=`stat "$FILE" -c%Y`
             if [ $AGE -gt $LASTMODIFIED ]; then
                 LASTMODIFIED=$AGE
             fi
        done

    # Otherwise, just get the modified time.
    else
        LASTMODIFIED=`stat "$TARGET/$NAME" -c%Y`
    fi

    TIME=`date +%s`
    DIFF=`expr $TIME - $LASTMODIFIED`

    # Remove the torrent if its older than the CUTOFF.
    if [ $DIFF -gt $CUTOFF ]; then
        date
        echo "Removing $NAME with ID:$ID"
        $BIN -n $USER:$PASS -t $ID --remove-and-delete
    fi

done

IFS=$OLDIFS
Run Code Online (Sandbox Code Playgroud)

但是当我尝试运行它时,我收到此错误:/root/transmission_r.sh: 1: /root/transmission_r.sh: #!/bin/sh: not found

Arj*_*jan 19

你的脚本开始于:

#!/bin/sh
Run Code Online (Sandbox Code Playgroud)

这不是注释,而是告诉您的操作系统用于执行脚本的shebang/bin/sh。但显然 Ubuntu 找不到它。

  • 如果ls /bin/sh显示没有结果,那么我想这需要修复。作为临时解决方案,您可能很幸运,您的脚本也适用于例如 bash:

    #!/bin/bash
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果/bin/sh 确实存在(就像它应该的那样),那么不知何故 Ubuntu 无法解释第一行。将其转储为十六进制:

    head -n 1 myscript.sh | hexdump -C
    
    00000000  ef bb bf 23 21 2f 62 69  6e 2f 73 68 0d 0a        |...#!/bin/sh..|
    
    Run Code Online (Sandbox Code Playgroud)

    结果是:

    • 确保行尾使用 Unix 格式 LF(\n或十六进制0a),而不是例如 Windows 标准 CRLF(\r\n或上例中的十六进制0d0a)。在 Mac 上,这实际上会引发不同的错误:

      /bin/sh^M: bad interpreter: No such file or directory
      
      Run Code Online (Sandbox Code Playgroud)
    • 确保文件编码不会混乱,例如(不可见的)Unicode BOMef bb bf在上面的示例输出中)。在上面的示例中,您的 shell 没有看到注释或 shebang,而是尝试运行以 3 个不可见字符开头的命令。在这种情况下,您的 shell 可能仍会执行下一行,甚至可能成功完成脚本。在 Mac 上,第一行实际上抛出:

      ./myscript.sh: line 1: #!/bin/sh: No such file or directory
      
      Run Code Online (Sandbox Code Playgroud)

要转储错误消息以查看该消息中的不可见字符,需要将错误输出重定向到标准输出:

./myscript.sh 2>&1 | hexdump -C

00000000  2e 2f 6d 79 73 63 72 69  70 74 2e 73 68 3a 20 6c  |./myscript.sh: l|
00000010  69 6e 65 20 31 3a 20 ef  bb bf 23 21 2f 62 69 6e  |ine 1: ...#!/bin|
00000020  2f 73 68 3a 20 4e 6f 20  73 75 63 68 20 66 69 6c  |/sh: No such fil|
00000030  65 20 6f 72 20 64 69 72  65 63 74 6f 72 79 0a     |e or directory.|
Run Code Online (Sandbox Code Playgroud)