防止一個指令在另一個指令之後執行

防止一個指令在另一個指令之後執行

我希望 shell 能夠警告我可能會犯的錯誤。

如何防止命令cmd2cmd1.

例如:

$ tar tf file.tar
$ rm !$

在這裡,我只是忘記了列出該文件而不是提取其內容。

我正在尋找一個通用的解決方案,它根據前一個命令的名稱和返回值以及當前命令進行選擇。

答案1

在 bash 中,您可以設定shopt -s histverify哪一項將阻止歷史記錄被一步展開和執行。這裡,第一次按 時,上面的內容$ rm !$將擴展為,允許您在再次按執行之前進行檢查或編輯。$ rm file.tarEnterEnter
更通用的解決方案將轉向“做我的意思”領土,需要一個程序來事後猜測你的意圖。

答案2

您要求很多通用答案,但在某種程度上應該可以相對容易地做到這一點。

然而,bash至少有兩種通用機制可以幫助解決這個問題。您可以設定變數 PROMPT_COMMAND,這將在您在提示符號中執行任何內容後執行:

$ PROMPT_COMMAND='echo BOFH says hi!'
BOFH says hi!
$ man man
BOFH says hi!
$

我們可以用它來保存最後輸入的命令,然後重新讀取它,這樣我們就可以將它存儲在內存中以供進一步使用(在這種情況下歷史擴展不起作用):

$ PROMPT_COMMAND='history -a; tail -n1 ~/.bash_history'
PROMPT_COMMAND='history -a; tail -n1 ~/.bash_history'
$ wc < test.sh | grep .
 5 11 63
wc < test.sh | grep .

現在是邏輯部分,這完全取決於你。讓我們使用非常簡單的邏輯來阻止問題中的範例。要記住的是,bash 函數仍然可以在那裡工作,因此您不必將所有內容塞到單行、單一變數中。

$ # define the logic check
$ checkSanity() { grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$@" && echo "be careful, don't delete this"; }
checkSanity() { grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$@" && echo "be careful, don't delete this"; }
$ # feed it the last command
$ PROMPT_COMMAND='history -a; last=$(tail -n1 ~/.bash_history); checkSanity "$last"'
$ # simple test
$ tar tf test.sh 2>/dev/null 
be careful, don't delete this
$ tar xf test.sh 2>/dev/null 
$

當然,這種方法對於防止 PEBKAC 很有用(特別是如果您sleep 3在末尾添加),但它本身無法破壞下一個命令。

如果那是真的你想要什麼,捕獲DEBUG信號(例如trap 'echo "I am not deterministic, haha"' DEBUG),因為它預先運行。結合這兩種方法時要小心,因為輸出/操作將加倍:

$ df
/.../
$ trap 'tail -n1 ~/.bash_history' DEBUG
df
df
trap 'tail -n1 ~/.bash_history' DEBUG
trap 'tail -n1 ~/.bash_history' DEBUG

若要讓陷阱中斷指令,您必須啟用extdebug( shopt -s extdebug)。您也不需要不斷保存和重新讀取歷史記錄,但可以檢查$BASH_COMMAND以獲取即將運行的命令。然後,您只需要確保邏輯檢查器在偵測到不良情況時傳回 1,否則傳回 0。

          extdebug
                  If set, behavior intended for use by debuggers is enabled:
    /.../
                  2.     If  the command run by the DEBUG trap returns a non-zero value, the next
                         command is skipped and not executed.


$ checkSanity() { if grep -q "tar  *[tf][[:alpha:]]*[tf] " <<< "$1"; then  echo "be careful, don't delete this"; return 1; fi; }
$ trap 'checkSanity "$BASH_COMMAND"' DEBUG
$ # simple test
$ tar tf test.sh 2>/dev/null 
be careful, don't delete this
$ tar xf test.sh 2>/dev/null 
$

答案3

在這種情況下,您將從命令的錯誤警告中受益rm

在 shell 初始化腳本中(假設bash, so ~/.bashrc),您可以rm使用-i或 的別名-I

alias rm="rm -i"

man 1 rm

   -i     prompt before every removal

   -I     prompt once before removing more than three files, or when
          removing recursively.  Less intrusive than -i, while still
          giving protection against most mistakes

更普遍的問題是“我如何保護我的系統免受我自己的侵害”之前討論過。簡而言之,注意你在做什麼,並且僅在root必要時運行命令。

答案4

根據您的具體情況,我會這樣做:

tar tf file.tar
if [ -f file ]; then   # Assuming you meant to extract a file
  rm -f file.tar
else
  echo "file is missing. Command failed."
fi

如果您想檢查錯誤並僅在第一個命令成功時執行下一個命令

some_command && another_command

儘管在您的特定情況下,第二個命令仍然會運行,因為它沒有錯誤,即使它沒有執行您想要的操作。

相關內容