使用空的shell变量时发出错误


22

有时我使用$PROJECT_HOME/*来删除项目中的所有文件。如果PROJECT_HOME未设置环境变量(因为我设置了环境变量,su并且新用户未设置此环境变量),它将开始从根文件夹中删除所有文件。这是世界末日。

bash在外壳中使用未定义的环境变量时,如何配置抛出错误?


5
set -u会做你想要的。
cuonglm

你能作为答案吗?

2
当然,您不会将var初始化为空字符串。[ -z "$VAR" ]也可以与未初始化的一起使用VAR。初始化只是为了显示不良行为-我的意思是,如果您的var确实以任何方式初始化为空字符串,而您rm -r "$PROJECT_HOME"/*错误地依赖运行set -u,您将得到“世界末日”的行为。IHMO,比起后悔,保护计算机的全部内容要好。set -u不安全。
PSkocik 2015年

3
“很长”?您不应该寻找手动执行危险操作的简便方法。相反,您应该创建函数,别名或脚本来执行所需的操作。在这种情况下,使用@PSkocik的建议命令创建别名既安全方便。
凯尔·斯特兰德

1
如果用户设置该PROJECT_HOME=/etc怎么办?仅检查一个空值还不足以防止灾难。以root身份运行时,不应使用不受信任用户的变量。
Barmar 2015年

Answers:


27

在POSIX shell中,可以使用set -u

#!/bin/sh

set -u
: "${UNSET_VAR}"

或使用参数扩展

: "${UNSET_VAR?Unset variable}"

在您的情况下,您应该使用:?而不是?来使设置但为空的变量也失败:

rm -rf -- "${PROJECT_HOME:?PROJECT_HOME empty or unset}"/*

17
[ -z "$PROJECT_HOME" ] || rm -r "$PROJECT_HOME"/*

这也将赶在那里的情况下PROJECT_HOME 设置,但不包含任何东西。

例:

1)这将删除您可以在系统上删除的几乎所有内容(禁止里面的点文件/(通常没有)):

set -u
PROJECT_HOME=
rm -r "$PROJECT_HOME"/*

2)这不会做任何事情:

PROJECT_HOME=
[ -z "$PROJECT_HOME" ] || rm -r "$PROJECT_HOME"/* 

完全删除项目主目录并重新创建它可能是另一个选择(如果您也想摆脱点文件的话):

#no apocalyptic threats in this scenario
rm -r "$PROJECT_HOME"
mkdir "$_" 

1
-z可以,但是由于$PROJECT_HOME应该是目录,所以可能-d会更好。[[ -d $PROJECT_HOME ]] && rm -r "$PROJECT_HOME"
kojiro

2
如果PROJECT_HOME设置为非目录,则这是非灾难性错误,可能是由于输入错误造成的。该-d检查将隐藏错误。我认为这是更好的,如果它不断的rmrm大声抱怨它。
PSkocik 2015年

2
如果设置了PROJECT_HOME,但名称不是目录,[[ -d $PROJECT_HOME ]] && rm -r "$PROJECT_HOME"则将无提示地执行任何操作。但是[[ -z $PROJECT_HOME ]] || rm -r "$PROJECT_HOME",即使它是不是目录的文件,也将以无提示方式删除“ $ PROJECT_HOME”。收到错误消息绝不是问题:if [[ -d $PROJECT_HOME ]]; then rm -r "$PROJECT_HOME"; else printf '%s is not a directory\n' "$PROJECT_HOME" >&2; fi
kojiro

1
现在“不小心”设置了PROJECT_HOME="/."……
哈根·冯·埃森2015年

1
@HagenvonEitzen如果将PROJECT_HOME设置为root,则清空PROJECT_HOME的过程将清空root。这是预期的和完全合理的行为。而且您甚至不需要最后一个点。
PSkocik

0

另一种方法是:

rm -r "${somevar:-/tmp/or_this_if_somevar_is_empty}"/*

变量替换有很多,上面的一个是“ somevar”为空(并且在这种情况下,它试图删除/tmp/or_this_if_somevar_is_empty/*


1
或者:rm -fr ${ENV_VAR:?suitably caustic message here}/*,但它可能仍然是值得检查该值不映射到根目录下,并指出,有很多方法来颠覆简单的测试:///../usr/who/../..,...
乔纳森·莱弗勒

是。如果你要使用参数扩展,你不妨用一个实际抛出一个错误
数字创伤
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.