我正在研究这个preinst文件的内容,该脚本在包从Debian归档文件(.deb)文件解压缩之前执行该文件。

脚本代码如下:

#!/bin/bash
set -e
# Automatically added by dh_installinit
if [ "$1" = install ]; then
   if [ -d /usr/share/MyApplicationName ]; then
     echo "MyApplicationName is just installed"
     return 1
   fi
   rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf
   rm -Rf $HOME/.local/share/file-manager/actions/*
fi
# End automatically added section

我的第一个问题是关于这一行的:

set -e

我认为脚本的其余部分非常简单:它检查Debian/Ubuntu包管理器是否正在执行安装操作。如果是,它将检查我的应用程序是否刚刚安装到系统上。如果有,脚本打印消息“MyApplicationName刚刚安装”并结束(返回1意味着以“错误”结束,不是吗?)

如果用户要求Debian/Ubuntu包系统安装我的包,脚本还会删除两个目录。

是这样吗,还是我漏掉了什么?


当前回答

Script 1: without setting -e
#!/bin/bash
decho "hi"
echo "hello"
This will throw error in decho and program continuous to next line

Script 2: With setting -e
#!/bin/bash
set -e
decho "hi" 
echo "hello"
# Up to decho "hi" shell will process and program exit, it will not proceed further

其他回答

如果命令或管道出现错误,Set -e将停止脚本的执行——这与默认shell行为相反,默认shell行为是忽略脚本中的错误。在终端中键入help set以查看此内置命令的文档。

我在试图弄清楚由于set -e而中止的脚本的退出状态是什么时发现了这篇文章。答案对我来说并不明显;因此有了这个答案。基本上,set -e终止命令(例如shell脚本)的执行,并返回失败命令的退出状态码(即内部脚本,而不是外部脚本)。

例如,假设我有一个shell脚本outer-test.sh:

#!/bin/sh
set -e
./inner-test.sh
exit 62;

inner-test.sh的代码是:

#!/bin/sh
exit 26;

当我从命令行运行outer-script.sh时,我的外部脚本以内部脚本的退出码终止:

$ ./outer-test.sh
$ echo $?
26

从帮助集:

  -e  Exit immediately if a command exits with a non-zero status.

但有些人(bash FAQ和irc freenode #bash FAQ作者)认为这是一种坏习惯。建议使用:

trap 'do_something' ERR

发生错误时运行do_something函数。

参见http://mywiki.wooledge.org/BashFAQ/105

如果命令失败,它将停止脚本的执行。

一个明显的例外是if语句。例如:

set -e
false
echo never executed
set -e
if false; then
  echo never executed
fi

echo executed

false

echo never executed

我相信这样做的目的是为了让这个剧本迅速失败。

要亲自测试,只需在bash提示符下键入set -e。现在,试着运行ls。您将得到一个目录列表。现在输入lsd。该命令无法识别,并将返回一个错误代码,因此bash提示符将关闭(由于set -e)。

现在,为了在“脚本”的上下文中理解这一点,使用这个简单的脚本:

#!/bin/bash 
# set -e

lsd 

ls

如果按原样运行,您将从最后一行的ls中获得目录列表。如果取消set -e的注释并再次运行,则不会看到目录列表,因为bash一旦遇到来自lsd的错误就会停止处理。