我有一个使用 shebang : 的脚本#!/bin/sh
,但是当我在我的 Ubuntu 14.04 终端中运行它时,它不起作用并且它说某些行有意想不到的运算符。
我的 MacOSX 朋友可以使用#!/bin/sh
shebang 运行该脚本。
我尝试将 shebang 改为#!/usr/bin/env bash
,然后脚本突然就运行成功了!这里到底发生了什么?
我真的希望我也可以运行!#/bin/sh
shebang,这样我就不需要更改我拥有的每个脚本。
答案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
了可能的bash
ism,其他返回值表示其他问题(文件不可读、缺少 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
。
推荐阅读:
- 巴什主义- 比较
bash
语法dash
并显示所需的更改。 - 破折号
/bin/sh
- 相似的。
答案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 -> dash
shell,这可能是您的发行版(例如 debian)中链接的默认 shell 。