2016-12-26 102 views
0

首先,我不知道我是否正确地制定问题。 所以我有一个bash脚本删除系统中的用户。问题是,它显示终端代码之前的错误信息。 这里。 代码:Bash脚本stderr和stdout

echo -e "\nCommencing user $UserName removal" 
echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName)" 
echo -e "Listing group(s) user: " "$(groups $UserName)" 
echo -e "Removing Crontab ... " "$(crontab -r -u $UserName)" 

这里是输出:

Commencing user Test2 removal 
chsh: unknown user: Test2 
Deactivating Test2 shell account ... 
groups: Test2: no such user 
Listing group(s) user: 
scripts/sudo.sh: line 332: /delete_Test2/crontab.bak: No such file or directory 
Saving Crontab ... 

删除的用户是Test2的,这是这种情况下“所谓的”不存在时(为不同的时间不同的问题)。现在,不应该将stderr味精显示在命令旁边还是下面,而不是上面呢?

预先感谢

回答

3

当shell执行行echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName)",这里是事件的顺序:

  1. 外壳运行chsh -s /usr/bin/false Test2,其标准输出去捕捉缓冲区,所以外壳以后可以使用它。
  2. chsh发现“Test2”不存在,并将“chsh:unknown user:Test2”打印到它的stderr。由于shell没有对stderr做任何特殊的处理,所以这直接到了shell的stderr,它是你的终端。
  3. chsh退出
  4. 壳取所捕捉的输出:从chsh(注意标准输出,而不是标准错误)(有没有任何),和替代入echo命令行,得到echo -e "Deactivating Test2 shell account ..." ""

注该错误信息被打印在第2步,但有关将要发生什么的消息直到第4步才会打印出来。

有几种方法可以解决此问题;通常最好的做法是避免捕获命令输出的整个混乱,然后回应它。这毫无意义,只会导致这样的混乱(以及其他一些你没有遇到过的)。只需直接运行该命令,并让其输出(stdout和stderr)按正常顺序进入正常位置。

顺便说一句,我也建议避免echo -e,或确实echo -anythingPOSIX standard for echo说“实现不应该支持任何选项。”实际上,有些实现可以支持选项;其他人只是将它们视为要打印的字符串的一部分。另外,一些解释转义序列(如\n)要打印的字符串中,有些则不需要,有些只在指定-e(违反POSIX标准)的情况下执行。鉴于这些功能是多么不可预测,最好避免这种不确定的情况,并且使用printf来代替(使用起来更复杂,但更可预测),或者(如您的情况),只需使用单独的echo命令线。

此外,你应该总是用双引号变量引用(以下EG groups "$UserName"代替groups $UserName),以防它们包含空格,通配符等

基于上述,这里就是我会写的脚本:

echo # print a blank line 
echo "Commencing user $UserName removal" 
echo "Deactivating $UserName shell account ..." 
chsh -s /usr/bin/false "$UserName" 

echo "Listing group(s) user: " 
groups "$UserName" 

echo "Removing Crontab ... " 
crontab -r -u "$UserName" 
+0

感谢大家。戈登,你和伊格纳西奥回答工作;然而,我从你身上学到的是,我不需要回应我的命令!并确保将用户名放在引号中以防万一。谢谢 – user3112318

1

现在,应该不是stderr的MSG显示旁边的命令或低于它,而不是上面呢?

不,因为命令先执行,然后然后它的输出被回显。在两个单独的行中执行回显和命令。

1

这是因为chsh写入stderr 之前 bash有机会写入stdout。将stderr重定向到标准输出正确:

echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName 2>&1)" 

通常,最好在尝试停用用户之前检查用户是否存在。