为什么我的脚本在执行命令后突然退出?

Joe*_*mme 2 bash shell wget exitstatus

我正在尝试按照以下说明为 Dash 生成文档集:http://kapeli.com/docsets。问题是,脚本在 wget 之后不会继续,并且似乎不会抛出任何错误。当我将脚本复制到终端时,一切正常。

我使用的是 MacOS 10.8.4 和默认的 bash。

#!/usr/bin/env bash
set -e

mkdir -p $1.docset/Contents/Resources/Documents/

echo "THIS RUNS"
wget -rkp -l3 -np -nH --cut-dirs=1 --directory-prefix="./"$1".docset/Contents/Resources/Documents/" $2
echo "THIS DOES NOT RUN"

sed "s/NAME/$1/g" template > $1.docset/Contents/Info.plist
touch $1.docset/Contents/Resources/docSet.dsidx
# (script continues) 
Run Code Online (Sandbox Code Playgroud)

我查看了其他帖子,例如My shell script stop after exec但我没有exec在这里使用。

为什么脚本会退出?

kon*_*box 5

您启用了set -e又名errexit.

如果其中一个命令返回非零退出代码,您的脚本将退出,并且具体失败的命令可能并不总是显而易见:

  • 有些可能会打印一个有用的错误来识别自身和问题
  • 有些(例如wget)可能会在输出的页面中简要提及错误方式
  • 有些(例如grep)可能根本不显示错误或任何输出,脚本只是退出

要了解哪个命令导致问题,请使用-xaka运行脚本xtrace

bash -x script.sh
Run Code Online (Sandbox Code Playgroud)

或者添加set -x到脚本本身:

set -x
set -e
...
Run Code Online (Sandbox Code Playgroud)

这将导致脚本打印出正在执行的每个命令,以便您可以看到哪一个是最后一个。

如果您想忽略命令的退出状态,您可以添加|| true

# Causes exit if you lack read permission on any directory
find . -name '*.sh' 

# Does not cause the script to exit
find . -name '*.sh' || true
Run Code Online (Sandbox Code Playgroud)

如果您希望set -e在脚本中触发时收到警报,您可以设置一个陷阱:

#!/bin/bash
set -e
# Show error if commands exit with non-zero
trap 'ret=$?; echo "$0:$LINENO: Error: set -e triggered"; exit $ret' ERR
# Would have failed silently
grep doesnotexist /etc/passwd
echo "This does not run"
Run Code Online (Sandbox Code Playgroud)

执行时:

$ ./foo
./foo:6: Error: set -e triggered
Run Code Online (Sandbox Code Playgroud)