linux script 什麼意思啊! 在shell中的命令之前?




shell script get pid (3)

問題出在標題中。 以感嘆號開頭的shell命令(shell腳本的一部分)的目的是什麼? 具體例子:

在foo.sh中:

#!/usr/bin/env bash
set -e
! docker stop foo
! docker rm -f foo
# ... other stuff

我知道如果沒有這個空間,感嘆號就會用於歷史替換 ! <expression> 根據 手冊頁的 ! <expression> 可用於評估“ 如果expr為false則為True ”。 但是在對我來說沒有意義的示例上下文中。


“!” 意思是“不”,所以當你把它放在一個命令之前然後你運行“$?” 它將回顯1.這意味著它失敗而不是0,這意味著成功。


如果您不希望腳本在兩種情況下都失敗,錯誤或命令成功,您也可以使用此替代方法:

set -e
docker stop foo || true

boolean 或true 使管道始終具有 0 作為返回值。


TL; DR:這只是在您使用它的特定行中繞過 set -e 標誌。

添加添加到 hek2mgl的正確和有用的答案 。

你有:

set -e
! command

Bash參考手冊→管道 描述:

管道中的每個命令都在其自己的子shell中執行。 管道的退出狀態是管道中最後一個命令的退出狀態(...)。 如果保留字'!' 在管道之前,退出狀態是 如上所述 的退出狀態的邏輯否定 。 shell在返回值之前等待管道中的所有命令終止。

這意味著 ! 在命令之前否定它的退出狀態:

$ echo 23
23
$ echo $?
0
                # But
$ ! echo 23
23
$ echo $?
1

要么:

$ echo 23 && echo "true" || echo "fail"
23
true
$ ! echo 23 && echo "true" || echo "fail"
23
fail

退出狀態在很多方面都很有用。 在腳本中,與 set -e 一起使用,只要命令返回非零狀態,腳本就會退出。

因此,當你有:

set -e
command1
command2

如果 command1 返回非零狀態,則腳本將完成,並且不會繼續執行 command2

但是,還有一個值得一提的地方,如 4.3.1 The Set Builtin中所述

-e

如果管道(請參閱管道)(可能包含單個簡單命令(請參閱簡單命令)),列表(請參閱列表)或複合命令(請參閱複合命令)返回非零狀態,請立即退出。 如果失敗的命令是緊跟在while或until關鍵字之後的命令列表的一部分,if語句中的部分測試,在&&或||中執行的任何命令的一部分,則 shell不會退出 列表除了最後的&&或||之後的命令,管道中的任何命令但是最後一個,或者 命令的返回狀態是否被反轉! 。 如果子shell以外的複合命令返回非零狀態,因為在忽略-e時命令失敗,則shell不會退出。 ERR上的陷阱(如果已設置)將在shell退出之前執行。

考慮到所有這些因素,當您有:

set -e
! command1
command2

你正在做的是繞過 command1set -e 標誌。 為什麼?

  • 如果 command1 正常運行,它將返回零狀態。 ! 否定它,但 set -e 不會觸發退出,因為它來自與!反轉的返回狀態,如上所述。
  • 如果 command1 失敗,它將返回非零狀態。 ! 將否定它,所以該行最終將返回零狀態,腳本將繼續正常。




sh