我遇到了這個很好的命令dmesg -w
,它會在插入/移除新設備時輸出設備信息。暫停bash腳本,直到「dmesg -w」輸出任何東西
有沒有辦法使用此命令來暫停腳本,直到用戶插入任何類型的USB或SSD卡?我想輸出重定向和使用read
莫名其妙的......
我normaly使用下面的兩個命令,從dmesg的獲取設備名稱:
SSD_DMESG=$(dmesg | tail -n1 | grep -o 'sd[[:lower:]]')
SSD=/dev/$SSD_DMESG
我遇到了這個很好的命令dmesg -w
,它會在插入/移除新設備時輸出設備信息。暫停bash腳本,直到「dmesg -w」輸出任何東西
有沒有辦法使用此命令來暫停腳本,直到用戶插入任何類型的USB或SSD卡?我想輸出重定向和使用read
莫名其妙的......
我normaly使用下面的兩個命令,從dmesg的獲取設備名稱:
SSD_DMESG=$(dmesg | tail -n1 | grep -o 'sd[[:lower:]]')
SSD=/dev/$SSD_DMESG
此腳本計算多少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
哦謝謝你,這是一個不錯的增量hehehe實施。 :d – 71GA 2014-10-04 01:13:10
udevadm
的monitor
模式將提供uevent
秒的飼料,因爲它們產生的:
還有這裏的幾件事情值得注意的是:
stdbuf
用於work aroundudevadm
的output buffering behavior。--line-buffered
告訴grep
輸出每一行,而不是將它保存在緩衝區中。<()
)用於將udevadm
的輸出轉換爲/dev/fd/*
符號鏈接,即grep
可以作爲文件打開並讀取。如果使用流水線(udevadm | grep
),即使在grep
進程退出後,udevadm
進程也可能最終掛起,這反過來會阻塞父進程。-m
。我剛剛剛剛解決了這個問題。我試圖監聽dmesg
,以便我可以在連接USB MIDI設備時發現它們。
首先,我們不要使用dmesg -w
,因爲這樣做也會顯示過去最近發生的事件。相反,讓我們tail /var/log/messages
在刷新模式,指定0
線最初將被顯示:
tail -f -n 0 '/var/log/messages'
現在,我們知道我們想要監視什麼命令,怎麼能等待新dmesg
條目,符合我們的標準,然後終止我們的投票?幸運的是,bash
重定向可以很容易地把任務放到後臺,並隨後訪問其STDOUT
和STDIN
:
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中記錄的幾個有用的備選方案。
你用什麼操作系統支持-D標誌到dmesg? – 2014-10-03 23:43:54
在Linux上,至少有更好的方法來觸發設備插入和刪除事件 - 您可以使用udev或與OS操作系統相同的操作,只在設備插入和刪除時觸發,而不需要持續監視。 – 2014-10-04 00:30:04
@Nick Russo我正在使用ArchLinux。 @Charles Duffy我沒有'udev',但是我有'udevadm'。 – 71GA 2014-10-04 01:10:35