2014-10-03 37 views
1

我遇到了這個很好的命令dmesg -w,它會在插入/移除新設備時輸出設備信息。暫停bash腳本,直到「dmesg -w」輸出任何東西

有沒有辦法使用此命令來暫停腳本,直到用戶插入任何類型的USB或SSD卡?我想輸出重定向和使用read莫名其妙的......

我normaly使用下面的兩個命令,從dmesg的獲取設備名稱:

SSD_DMESG=$(dmesg | tail -n1 | grep -o 'sd[[:lower:]]') 
SSD=/dev/$SSD_DMESG 
+3

你用什麼操作系統支持-D標誌到dmesg? – 2014-10-03 23:43:54

+1

在Linux上,至少有更好的方法來觸發設備插入和刪除事件 - 您可以使用udev或與OS操作系統相同的操作,只在設備插入和刪除時觸發,而不需要持續監視。 – 2014-10-04 00:30:04

+0

@Nick Russo我正在使用ArchLinux。 @Charles Duffy我沒有'udev',但是我有'udevadm'。 – 71GA 2014-10-04 01:10:35

回答

2

此腳本計算多少sd[[:lower:]]線是目前在dmesg隊列。然後等待更多的線出現。當他們這樣做時,它打印它們:

#!/bin/sh 
n=$(dmesg | grep 'sd[[:lower:]]' | wc -l) 
while [ "$n" -eq "$(dmesg | grep 'sd[[:lower:]]' | wc -l)" ] 
do 
     sleep 0.1s 
done 
sleep 0.1s 
dmesg | grep 'sd[[:lower:]]' | tail -n+$n 

wc -l用於提供一個行數。 tail -n+$n用於刪除以前的現有線路。最後的sleep的目的是爲了讓內核完成處理設備的時間。

以上內容冗長。如果你只是想在sd?符號,沒有其他信息,請嘗試:

#!/bin/sh 
n=$(dmesg | grep -o 'sd[[:lower:]]' | wc -l) 
while [ "$n" -eq "$(dmesg | grep -o 'sd[[:lower:]]' | wc -l)" ] 
do 
    sleep 0.1s 
done 
sleep 0.1s 
dmesg | grep -o 'sd[[:lower:]]' | tail -n+$n | sort -u 
+0

哦謝謝你,這是一個不錯的增量hehehe實施。 :d – 71GA 2014-10-04 01:13:10

2

udevadmmonitor模式將提供uevent秒的飼料,因爲它們產生的:

​​

還有這裏的幾件事情值得注意的是:

  • stdbuf用於work aroundudevadmoutput buffering behavior
  • --line-buffered告訴grep輸出每一行,而不是將它保存在緩衝區中。
  • BASH process substitution<())用於將udevadm的輸出轉換爲/dev/fd/*符號鏈接,即grep可以作爲文件打開並讀取。如果使用流水線(udevadm | grep),即使在grep進程退出後,udevadm進程也可能最終掛起,這反過來會阻塞父進程。
  • 刪除連續流的參數-m
1

我剛剛剛剛解決了這個問題。我試圖監聽dmesg,以便我可以在連接USB MIDI設備時發現它們。

首先,我們不要使用dmesg -w,因爲這樣做也會顯示過去最近發生的事件。相反,讓我們tail /var/log/messages在刷新模式,指定0線最初將被顯示:

tail -f -n 0 '/var/log/messages'

現在,我們知道我們想要監視什麼命令,怎麼能等待新dmesg條目,符合我們的標準,然後終止我們的投票?幸運的是,bash重定向可以很容易地把任務放到後臺,並隨後訪問其STDOUTSTDIN

exec 3< <(tail -f -n 0 '/var/log/messages')

在這裏,我們重定向我們tail操作的輸出到文件描述符3,這我們可以取消設置,一旦我們遇到我們的標準如下:

exec 3>&-

注意,設置文件描述符也終止(通過SIGPIPE)綁定的命令,所以在這種情況下,我們不必擔心清理tail操作。

現在我們知道如何綁定和解除綁定我們的背景執行命令的文件描述符,我們可以執行while循環,將read和處理文本的每一行通過文件描述符3提供:

exec 3< <(tail -f -n 0 '/var/log/messages') 

local line 

while IFS='' read line 
do 
    : 
done <&3 

read命令將耐心地等待文本描述符3上出現的新文本行,並且while命令將循環直到read命令表示沒有更多行文本要讀取。 read只有在文件描述符3關閉時纔會這樣做,並且由於該描述符綁定到tail -f,因此它永遠不會自動關閉其輸出,因此while循環不會終止,因此我們必須手動中斷循環。

現在我們可以添加一個以某種方式評估$line的語句,並在某些特定條件匹配時打破循環。在這裏,我們可以使用的grep -o成功的狀態,以確定我們已經找到了我們要找的,如果是的話,做一些適當的,包括打破循環,然後關閉文件描述符3

exec 3< <(tail -f -n 0 '/var/log/messages') 

local line 

while IFS='' read line 
do 
    echo "${line}" | grep -o 'sd[[:lower:]]' && { 

    echo "YAY! ${line} matched." 
    break 
    } 
done <&3 

exec 3>&- 

如果要以這種方式實施不使用bash文件重定向的解決方案,請參閱Bash: Capture output of command run in background中記錄的幾個有用的備選方案。