誤執行了rm rf 之後

2021-10-06 10:11:38 字數 3373 閱讀 5592

先來一段引發錯誤的**:

lic_path=

`pwd

`new_lic_dir=

`$[lic_path]/new_license`

old_lic_dir=

`$[lic_path]/old_license`

rm -rf $new_lic_dir/* 2>>/dev/null

rm -rf $old_lic_dir/* 2>>/dev/null

這裡解釋一下**段中2>>/dev/null的意思:

其中前面的數字可以是0,1,2,且每個數字分別代表標準輸入,標準輸出和錯誤輸出,/dev/null代表的是linux的空裝置檔案,所有往這個檔案裡寫入的內容都會丟失

拓展內容:

2>&1>/dev/null表示把錯誤輸出2重定向到標準輸出1,也就是螢幕,標準輸出寫入linux的空裝置檔案,也就是標準輸出進入「黑洞」,錯誤輸出列印到螢幕。其中「&」的作用,如果只有數字1則該**代表錯誤輸出寫入檔案1,加上「&」後表明1是標準輸出

回歸主題

既然發生了rm -rf /*的現象,那必然是new_lic_dir這個變數是空的,所以導致執行rm -rf $new_lic_dir /*這條語句的時候,變成了rm -rf /*刪庫語句。

這裡提到了在編寫shell語句**的時候的乙個用法,反引號「`」

源**中對變數new_lic_dir和變數old_lic_dir賦值的時候使用了反引號,而反引號在shell命令列中會被認為是命令優先執行,將輸出結果放入主命令後,主命令再被執行。也就是說,源**中new_lic_dir的值是$/new_license這條命令執行的結果,然後這條**沒有意義,所以返回空值給new_lic_dir變數。

反引號很多時候常見於lic_path='pwd'語句,**pwd用於返回當前所在目錄路徑

解決辦法:將反引號改為雙引號

對於誤操作的rm -rf /*,不要急忙重啟伺服器,或者關閉ssh連線的會話,而是要保留案發現場,接著查查還剩下什麼檔案。事實上,在誤操作執行的過程中,如果第一時間發現錯誤並立馬掐斷正在執行的指令碼,並非linux所有的檔案都被刪除了。

下面介紹幾個技巧:

cd + tab會返回指定目錄下的所有檔案,用來確認哪些系統檔案被刪除了,這樣雖然可能ls的命令被誤刪除了還能檢視每個目錄下的檔案。

rm -rf刪除目錄時要判斷目錄

#!/bin/bash

work_path=

`pwd

`#如果目錄不為空,才執行刪除操作

if[$

!=""];

then

rm -rf $/*

fi

shell指令碼指定set -u,執行指令碼時,如果遇到不存在的變數,bash缺省會忽略它,最好的情況應該是遇到變數不存在,指令碼應該報錯,而不是一聲不響的往下執行。通過set -u加在指令碼中,遇到不存在的變數就會報錯,並停止執行

#!/bin/bash

set -u

rm -rf $a/*

echo hello

這段**中變數$a是乙個不存在的變數,執行的結果如下:

$bash test.sh

test.sh:line4:a:unbound variable

可以看到,因為a是未定義的變數,指令碼自動報錯並且不執行後面的echo語句

建立**站機制,類似windows系統的**站機制,即使誤刪了也可以在**站恢復。實現思路:

刪除檔案時,並不真正執行刪除操作,而是將檔案移動到乙個特定目錄,可以設定定時清除**站,或者在**站裡面的檔案大小打到一定容量時(或者用時間作判斷)執行刪除操作以騰出空間。可以寫個shell指令碼替換rm命令,或者在需要刪除檔案時使用mv命令將檔案移動到「**站」

# 建立**站

mkdir /home/.trash

# 編寫remove.sh指令碼

trash_dir=

"/home/.trash"

for i in$*;

do stamp=

`date +%s`

filename=

`basename $i`

# 將對應檔案mv 至 .trash目錄

mv$i

$/$.

$done

# 修改~/.bashrc,用我們自建的remove.sh替代rm 命令

alias rm=

"sh /home/remove.sh"

# 設定crontab,定期清空**站,如每天0點清空

0 0 * * * rm -rf /home/.trash/*

# 最後使設定生效

source ~/.bashrc

這裡再介紹一下定時任務crontab和alias命令

類似上面的**段中的定時任務命令,定時任務crontab執行的命令段格式如下:

minute hour day month week command

其中:minute: 表示分鐘,可以從0到59之間的任何整數

hour: 表示小時,可以是從0到23之間的任何整數

day: 表示日期,可以是從1到31之間的任何整數

month: 表示月份,可以是從1到12之間的任何整數

week: 表示星期幾,可以是從0到7之間的任何整數,這裡的0或者7代表星期日

command: 表示要執行的命令,可以是系統命令,也可以是自己編寫的指令碼檔案

在以上各個欄位中,可以使用特殊字元:

星號(*):代表所有可能的值,例如month欄位如果是星號,則表示在滿足其他欄位的制約條件下每月都執行該命令

逗號(,):可以用逗號隔開的值指定乙個列表範圍,例如,「1,2,5,7,8,9」

中槓(-):可以用整數之間的中槓表示乙個整數範圍,例如「2-6」表示「2,3,4,5,6」

正斜線(/):可以用正斜線指定時間的間隔頻率,例如「0-23/2」表示每兩小時執行一次。同時正斜線可以和星號一起使用,例如*/10,如果用在minute欄位,表示每十分鐘執行一次。

linux的alias命令格式為:alias [別名]=[指令名稱],這裡的指令名稱就是命令列,注意,alias的效力僅及於該次登入的操作,如果要每次登入是自動設好別名,可在/etc/profile或者自己的~/.bashrc中設定指令的別名

執行 rm rf 之後

本文只是記錄一下自己在執行了rm rf 之後的心路歷程以及過後的乙個解決思路,並不是純技術解決方案。慎用 rm rf 說來慚愧,感謝部門領導對我的百般信任,讓我在剛畢業的時候就能在開發之餘,監管部門的伺服器。正是因為如此,我也有幸在手速足夠快的情況下,將原本的rm rf 按成了rm rf 原來是要刪...

linux下後台執行了php檔案之後如何進行終止

1 第一種方式 檢視正在執行的程序 ps ef grep serve.php ps 將某個程序顯示出來 a 顯示所有程式。e 此引數的效果和指定 a 引數相同。f 顯示 uid,ppip,c 與stime 字段。grep命令是查詢 關閉程序 kill 引數 程序號 kill 9 4394 kill ...

DispatcherTimer 停止執行了?

最近在專案中 fix 了乙個和 dispatchertimer 有關的 bug 程式中有乙個 dispatchertimer,每隔一段時間 例如 1s 執行一次,主要就是為了獲得當前的時間,然後根據時間做一些更新。但是在某些時刻,該 dispatchertimer 停止執行了。在解釋原因之前先解釋以...