先來一段引發錯誤的**:
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 停止執行了。在解釋原因之前先解釋以...