使用“#!/bin/sh”运行时脚本不起作用

使用“#!/bin/sh”运行时脚本不起作用

我有一个使用 shebang : 的脚本#!/bin/sh,但是当我在我的 Ubuntu 14.04 终端中运行它时,它不起作用并且它说某些行有意想不到的运算符。

我的 MacOSX 朋友可以使用#!/bin/shshebang 运行该脚本。

我尝试将 shebang 改为#!/usr/bin/env bash,然后脚本突然就运行成功了!这里到底发生了什么?

我真的希望我也可以运行!#/bin/shshebang,这样我就不需要更改我拥有的每个脚本。

答案1

/bin/sh你朋友在另一台电脑上可能使用已链接到 的操作系统/bin/bash。在 Ubuntu(实际上是 Debian 和大多数 Debian 衍生产品)中,/bin/sh不是链接到/bin/bash,而是链接到/bin/dash,它不支持许多bash特定的功能,但速度要快得多。

在 Arch Linux 上:

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Sep 28 15:26 /bin/sh -> bash

在 Ubuntu 上:

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 19  2014 /bin/sh -> dash

正确的做法

如果您使用 shebang,请认真对待。由于您的脚本包含bash-isms,请/bin/bash在 shebang 中使用。或者编写可移植的、符合 POSIX 的代码。

您可以使用以下方法加速此过程checkbashisms提及的程序这篇 LWN 文章。它是软件包的一部分devscripts,因此请先安装它:

sudo apt-get install devscripts

因此:

checkbashisms /path/to/script.sh || sed -i '1 s;/bin/sh;/bin/bash;' /path/to/script.sh

您可以将其转换为脚本(例如convert.sh):

#! /bin/sh

for i
do
    checkbashisms "$i"
    if [ $? = "1" ]
    then
        sed -i '1 s;/bin/sh;/bin/bash;' "$i"
    fi
done

特定的返回代码意味着1发现checkbashisms了可能的bashism,其他返回值表示其他问题(文件不可读、缺少 shebang 等),因此我们可以检查该特定的返回值。

然后使用以下命令调用它:

./convert.sh /path/to/first/script.sh /path/to/second/script.sh
# or 
./convert.sh *.sh
# or
find . -iname '*.sh' -exec ./convert.sh {} +

错误的做法

/bin/sh用 的符号链接替换/bin/bash

推荐阅读:

答案2

IFS就我而言,问题在于 ~/.bashrc (~/.profile) 中变量定义 的导出

#Loop over filenames with spaces
export IFS=$'\n'

当更改为
export IFS=$' \t\n' #default according to man dash

IFS=$'\n'
#!/bin/sh 脚本时,它们会再次开始工作。在后一种情况下,定义不再传播到分叉的 /bin/sh 进程。IFS 的含义解释如下这里并将其设置为 '\n' 会导致脚本解释出现问题短跑/bin/sh -> dashshell,这可能是您的发行版(例如 debian)中链接的默认 shell 。

相关内容