history命令_Linux history命令:檢視和執行歷史命令

2020-07-16 10:04:29
今天我們要介紹的 history 是 Linux 中的 history 命令。

“使用 Linux 系統總是要輸入大量的命令吧?”“嗯嗯。”
“這些命令裡一定有不少是重複的吧?”“還真是。”
“是不是感覺輸入重複命令很浪費生命?”“唉,說多了都是淚。”
“那想不想減少重複命令的輸入從而節省時間呢?”“必須的啊!”

如果真是這樣的話,那麼今天你有福啦,本文就是要與大家一起來學習減少重複命令輸入的各種技巧。

列出曾經輸入的命令

要減少輸入,首先要知道曾經輸入過什麼命令,對於這個問題,Linux 有很好的解決方案,它就是今天的主角——history。

我們直接輸入 history 命令:
[[email protected] ~]$ history
    1  cat .bash_history
    2  echo "" > .bash_history
    3  ls
    4  man ls
    5  date
    6  logout
    7  history

看到了什麼?是不是曾經輸入的命令都列了出來。但這裡有一個問題,雖然命令都列了出來,但沒有時間戳呀,也不知道命令是什麼時候執行的,這怎麼能稱得上是“history”呢?不用擔心,我們試試下面的命令。
#我們設定了一個環境變數
[[email protected] ~]$ export HISTTIMEFORMAT='%F %T '
 
#再來看history
[[email protected] ~]$ history
    1  2016-04-06 12:15:59 cat .bash_history
    2  2016-04-06 12:15:59 echo "" > .bash_history
    3  2016-04-06 12:15:59 ls
    4  2016-04-06 12:15:59 man ls
    5  2016-04-06 12:15:59 date
    6  2016-04-06 12:15:59 logout
    7  2016-04-06 12:16:16 history
    8  2016-04-06 12:18:15 export HISTTIMEFORMAT='%F %T '
    9  2016-04-06 12:18:20 history
看看是不是已經給命令打上了時間的烙印了。

雖然時間戳出現了,但還有兩個問題困擾著我們:
  1. 系統是怎麼知道我們在什麼時間執行了哪些命令呢?
  2. 有沒有發現,輸出內容中的前 6 條命令的時間戳竟然是完全一樣的,都是“2016-04-0612:15:59”,這又是為什麼呢?

我們先來重新登入一下系統,然後輸入下面的命令,一起來尋找問題的答案:
[[email protected] ~]$ cat .bash_history
 
cat .bash_history
echo "" > .bash_history
ls
man ls
date
logout
#1459916176
history
#1459916295
export HISTTIMEFORMAT='%F %T '
#1459916300
history
#1459916459
logout

看到檔案中的“#1459916176”這種格式的字串了嗎?這些就是命令執行的時間戳,通過這些標記,history 就能正確顯示命令的執行時間了。

為什麼前 6 條命令的時間戳是一樣的呢?這是因為這些命令執行時沒有開啟“時間戳記錄功能”,在後面需要顯示時間戳時,它們只能取距離它們最近的有時間記錄的那個時間點作為它們的時間戳。這也就是前 6 條命令所顯示的時間戳都是同一個時間點的原因。

重複上一次的執行

平時大家最常遇到的一個場景應該是“想重複執行上一條命令”,對於這種情況,我們首先想到的方法就是按“上方向鍵”,但其實我們有四種方法可以實現這一效果:
  1. 使用向上方向鍵,並回車執行。
  2. 輸入 !!,並回車執行。
  3. 輸入 !-1,並回車執行。
  4. 輸入 Ctrl+P 組合鍵並回車執行。

嘆號定位法

如果想執行以前執行過的某條命令,該怎麼辦呢?這也是一種經常會遇到的情況,下面我們就一起來看看:
[[email protected] ~]$ history
    7  ls
    8  vi test.go
    9  ls
   10  history
   11  export HISTTIMEFORMAT='%F %T'
   12  histroy
   13  export HISTTIMEFORMAT='%F %T'
   14  history
   15  export HISTTIMEFORMAT=
   16  man grep
   17  ls
   18  ll
   19  history

看到 man grep了嗎?假設這條命令就是你想執行的命令,你可以先記下它前面的標號 16,然後這樣來執行:
[[email protected] ~]$ !16
Ctrl+R 搜尋曾經的命令

上面的嘆號定位法雖然好用,但有個缺點,就是不太方便,這個方法需要我們先找出命令的編號,然後才能執行。下面,我們再為大家介紹一種更方便的方法,那就是“搜尋定位法”。

搜尋定位法,就是通過 Ctrl+R 來實現歷史命令關鍵字的搜尋功能,快速查詢到要執行的命令並執行。

下面,同學們可以嘗試一下,在你們的 Shell 中按一下 Ctrl+R 組合鍵,是不是會出現下面的提示:
(reverse-i-search)`':

然後輸入一些關鍵字,比如“man”:
(reverse-i-search)`man': man grep

系統是不是就找到 man grep 這條歷史命令了,如果這條命令正是你想要執行的,那麼就直接回車,命令就會立即執行了。

注意:如果找到的命令和想執行的命令稍微有點不同的話,你可以按一下向左或向右方向鍵來對命令進行微調,等調整成你想要執行的命令後,再按回車執行。

清除所有的命令

安全是計算機世界裡的頭等大事,出於安全的考慮,我們常常需要清除曾經輸入的命令,避免被其他別有用心的人看到。這種情況下,我們就要用 -c 選項來幫忙了。
[[email protected] ~]$ history -c

-c表示 clear,只要一執行,那麼我們的歷史命令列表瞬間就變得一乾二淨了,曾經的歷史命令統統不見了,這樣我們就再也不用擔心資訊洩露了。

其實,你想刪除歷史記錄可沒那麼容易,上面的方法其實只是個障眼法,它只是讓系統暫時不顯示歷史命令。當你再次重新登入系統後,以前的歷史就又會重新出現。

我們試了一下,確實是這樣子的,這到底是怎麼一回事呢?

事情的真相是這樣的:history-c 命令刪除的只是 Linux 系統記憶體中的歷史命令,當 Shell 退出時,就不會有歷史命令追加到檔案 .bash_history 中。但當重新登入到 Shell 時,Shell 便會載入檔案 .bash_history,該檔案中儲存著曾經輸入的歷史命令,因此,系統的歷史命令就又出現了。

那麼如何真正徹徹底底地刪除所有的歷史命令呢?我們可以採用以下方法。
[[email protected] ~]$ history -c
[[email protected] ~]$ history -w

history-w 的作用就是用記憶體中的歷史命令覆蓋 .bash_histroy 檔案的內容,這樣,即使 Shell 重新載入也載入不到任何命令了,因為此時 .bash_history 檔案中已經空空如也了。

history的設定

工欲善其事,必先利其器,科學地設定 history 命令,可以大大提高我們的工作效率,下面我們就來看看 history 都有哪些設定項。

(1) 設定歷史記錄的時間:
export HISTTIMEFORMAT='%F %T '     # 注意有個空格, 這樣在顯示時日期與命令之間會有空格分隔

(2) 控制歷史命令記錄的總個數:
export HISTSIZE=1000         # 設定記憶體中的history命令的個數
export HISTFILESIZE=1000     # 設定檔案中的history命令的個數

(3) 更換歷史命令的儲存位置:
一般情況下,歷史命令會被儲存在 ~/.bash_history 檔案中。如果不想儲存在這個檔案中,而想儲存在其他檔案中,那麼可以通過下面的方式來更改:
export HISTFILE=~/history.log

(4) 還有很多更加個性化的設定供大家選擇:
export HISTCONTROL=erasedups    # 清除整個命令歷史中的重複條目
export HISTCONTROL=ignoredups   # 忽略記錄命令歷史中連續重複的命令
export HISTCONTROL=ignorespace  # 忽略記錄空格開始的命令
export HISTCONTROL=ignoreboth   # 等價於ignoredups和ignorespace

尊重重要命令的隱私

試想一下,我們操作 Linux 系統,如果把所有的命令都記錄到 .bash_history 中,會不會有風險呢?

當然有風險啦,如果哪一天我們不幸中招,駭客攻入了我們的系統,他只要檢視一下 history 就能知道我們的很多秘密,比如一些登入密碼。為了避免該類事情的發生,我們希望 history 不要顯示含有隱私資訊的歷史命令,只顯示不含有隱私資訊的命令。這個需求太個性化,但 history 仍然能夠實現,下面我們就為大家介紹兩種行之有效的解決方案。

第一種靠譜的解決方案:
  • 第1步:設定 HISTCONTROL 環境變數:export HISTCONTROL=ignorespace。
  • 第2步:輸入重要命令時,記得在輸入命令前加上空格。
  • 第3步:執行 history,可以看到剛輸入的重要命令沒有出現在 history 中。

通過設定 HISTCONTROL=ignorespace,可以讓 history 不記錄你的特殊輸入(命令前加空格),這樣可以在一定程度上有效地保護我們的系統。

第二種靠譜的解決方案:
  • 第1步:設定 HISTIGNORE 環境變數 export HISTIGNORE=*。
  • 第2步:輸入重要命令,比如 mysql-uroot-p123。
  • 第3步:檢視你的 history,可以看到剛輸入的 mysql 命令沒有記錄在 history 中。
  • 第4步:恢復命令的記錄 export HISTIGNORE=。
  • 第4步後,系統又恢復正常,輸入的命令又能被正常記錄了。

這個方法雖然略顯煩瑣,需要你每次在輸入重要命令時都要先設定 HISTIGNORE=*,執行完命令後再設定 HISTIGNORE=,但是,這種方法能規避由於你的粗心大意(忘記命令前加空格)帶來的巨大安全隱患,確保機密資訊不會被洩露出去。