我已经通过使用 成功编写了可移植的、功能齐全的 shell 脚本/bin/sh
,例如:
#!/bin/sh
trap 'echo "Error on line $LINENO"; exit 1' ERR
while read LINE
do
echo "+ $LINE"
done < file.txt
这在 BSD 上有效,因为/bin/sh
它通常是ksh
$ ls -li /bin/{sh,ksh}
26768 -r-xr-xr-x 3 root bin 418612 Jun 18 17:41 /bin/ksh
26768 -r-xr-xr-x 3 root bin 418612 Jun 18 17:41 /bin/sh
而在 MacOS 和许多 Linux 发行版上,只需符号链接/bin/sh
到bash
$ ls -li /bin/{sh,bash}
17170438 -rwxr-xr-x 1 root root 938832 Jul 18 2013 /bin/bash
17170540 lrwxrwxrwx 1 root root 4 Feb 19 12:42 /bin/sh -> bash
如果这两个条件都满足,那么我可以使用 KSH 和 BASH 共有的相对丰富的功能集。在 Ubuntu 上,默认 shell 仅支持POSIX 功能。是否仍然可以编写包含错误处理的跨平台 shell 脚本?
编辑(2014-08-18)
我想到的解决办法是自动升级如果给定的 shell 不能理解 ERR 陷阱,则执行脚本
#!/bin/sh
trap 'echo "Error on line $LINENO"; exit 1' ERR || exec bash $0 "$@"
这样,我就可以编写合理可移植的 shell 脚本,仅当默认 shell 不支持 KSH 功能时才需要 bash。
答案1
如果您想编写可移植的 shell 脚本,您应该坚持使用 POSIX,因为这是 Unix 世界中最可靠的标准。
依赖/bin/sh
于 Bourne shell 以外的任何东西都是不好的做法,并且迟早会被打破。
由于 POSIX 不支持ERR
陷阱,您必须使用 手动将错误处理程序添加到您想要的任何命令中||
。例如:
#!/bin/sh
error(){
echo "Error at $1"; exit 1 ## we don't have $LINENO in POSIX
}
while read LINE
do
echo "+ $LINE"
false
done < file.txt || error "while loop"