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

Bash 为什么我的脚本在执行命令后突然退出?,bash,shell,wget,exitstatus,Bash,Shell,Wget,Exitstatus,我正试图按照以下说明为Dash生成文档集:。 问题是,该脚本在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

我正试图按照以下说明为Dash生成文档集:。 问题是,该脚本在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) 
我看了其他帖子,比如,但我没有在这里使用
exec


脚本为什么退出?

更新

我最初的回答是对你的问题的误解。一个似乎是问题的问题是您的:

INSERT INTO searchIndex (name, type, path) VALUES (index, Guide, 'index.html');
我不确定。但似乎您可能希望创建
索引
指南
字符串,如下所示:

INSERT INTO searchIndex (name, type, path) VALUES ('index', 'Guide', 'index.html');

您启用了
set-e
aka
errexit

如果其中一个命令返回非零退出代码,脚本将退出,并且可能并不总是很明显哪个命令失败:

  • 有些人可能会打印一个有用的错误来识别自己和问题
  • 一些(如
    wget
    )可能会在返回的一页页输出中简要地提到一个错误
  • 有些(如
    grep
    )可能根本不显示错误或任何输出,脚本只是退出
要知道哪个命令导致问题,请使用
-x
aka
xtrace
运行脚本:

bash -x script.sh
或者将
set-x
添加到脚本本身:

set -x
set -e
...
这将导致脚本打印出正在执行的每个命令,以便您可以看到最后一个命令

如果要忽略命令的退出状态,可以添加
| | 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
如果希望在脚本中触发
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"
执行时:

$ ./foo
./foo:6: Error: set -e triggered

尝试使用here文档,如下所示:

cat > "$1.docset/Contents/Info.plist" << EOF
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <plist version="1.0">
  <dict>
    <key>CFBundleIdentifier</key>
    <string>$1</string>
    <key>CFBundleName</key>
    <string>$1</string>
    <key>DocSetPlatformFamily</key>
    <string>$1</string>
    <key>isDashDocset</key>
    <true/>
  </dict>
  </plist>
EOF

cat>“$1.docset/Contents/Info.plist”wget的退出状态8意味着其中一个文件服务器返回了错误(例如404):

服务器发出了错误响应

您可能希望修复URL,使其指向正确的URL,或者忽略
wget
的退出状态,例如

wget ... || true
注意:除非启用了
pipefail
选项,否则上述操作将有效

另一种方法是比较退出状态,并在返回时忽略8,例如:

wget ... || { [ $? -ne 0 ] && [ $? -ne 8 ] && echo Success || exit 1; } 

请参阅:

按照预期,$1(文档集的名称)被连接到前缀中。是否有更好的(正确的、不中断的)方法来执行此操作?是否可以共享用于命令行参数的值?尝试一下,就像在wget完成之前它工作正常一样,然后忽略所有其他内容。@basszwo您没有看到其他人运行吗?这是wget的问题。您是否可以向其添加
-v
-verbose
选项以查看可能的错误消息。Wget收到了大量404错误,并返回退出状态8(echo$?)。实际问题解决了,但是,我仍然不知道该怎么办:删除“set-e”很好,但感觉不对。@basszwo您还应该引用变量,以防止分词,这会导致您的参数和文件创建不同。e、 g.
“--directory prefix=./$1.docset/Contents/Resources/Documents/”“$2”
我怀疑
set-e
导致$1变为
-e
。如果我错了,请纠正我。没错,谢谢。但这并不能解决问题。wget行之后的任何内容都将被完全忽略。