為什麼這個腳本在使用 crontab 自動執行時會輸出損壞的文件?
我有一個腳本可以掃描文件夾中的所有 .mp3 文件並創建索引。接下來它等待5s,否則它不能正常工作。最後,它會從歌曲名稱中刪除壞字元。
我使用 sudo crontab 自動執行它:
#!/bin/bash #Creates index file. find /var/www/html/uploads/Music/ -name '*.mp3' > /var/www/html/uploads/Music/songs.index | sleep 5s | sudo sed -i -e 's/\/var\/www\/html/\.\./g' /var/www/html/uploads/Music/songs.index
出於某種原因,當它通過 crontab 執行時,它會創建一個必須轉換為文本並返回索引才能讀取的文件。當您手動執行相同的腳本時,它可以正常工作。我錯過了什麼?
crontab 文件:
1 * * * * /home/aaeadmin/bin/midnightRun.bash
這可能是因為您在管道中執行命令。
管道的每個部分同時啟動,並與同一管道的其他部分同時執行。這意味著該
find
命令與該命令的啟動時間完全相同sed
。只有通過管道傳遞的數據,從一個命令的標準輸出到下一個命令的標準輸入,才能同步不同的命令。另請注意,您實際上並未使用管道的管道方面。命令之間沒有數據傳遞。
你的腳本最好寫成
#!/bin/bash #Creates index file. find /var/www/html/uploads/Music/ -name '*.mp3' > /var/www/html/uploads/Music/songs.index sed -i -e 's/\/var\/www\/html/\.\./g' /var/www/html/uploads/Music/songs.index
在這裡,
find
命令將在sed
命令開始之前完成執行。我還刪除了該sudo
命令,因為它顯然不需要(如果find
可以寫入文件,則sed
可以在沒有 的情況下讀取和修改它sudo
)。如果您發現確實需要
sudo
寫入songs.index
,我建議您改為在屬於有權寫入目標目錄的使用者的 crontab 中執行此 cron 作業/var/www/html/uploads/Music
。流水線解決方案將是
#!/bin/sh #Creates index file. find /var/www/html/uploads/Music/ -name '*.mp3' | sed -e 's,^/var/www/html,..,' >/var/www/html/uploads/Music/songs.index
這裡,直接
find
寫入命令,命令的結果寫入索引文件。來自into的數據(路徑名)通信使兩個程序保持同步,並在繼續之前等待產生下一行輸入(反之亦然;在嘗試輸出更多數據之前將等待處理數據)。sed``sed``find``sed``sed``find``find``sed
我還使
sed
命令更易於閱讀,並將正則表達式錨定到行首,並g
在末尾刪除了不必要的標誌。由於它現在從find
命令中讀取,因此我還刪除了該-i
選項(嚴格來說,該-e
選項也可以刪除)。我改變的另一件事是
#!
線路。您沒有使用任何bash
特定的功能,因此我們不妨使用(可能)更輕量級的 shell 來執行腳本。如果您想將找到的文件的文件名寫入索引,並
/var/www/html
替換為初始文件名,..
您也可以直接從find
:#!/bin/sh #Creates index file. find /var/www/html/uploads/Music/ -type f -name '*.mp3' -exec sh -c ' for pathname do printf "../%s\n" "${pathname#/var/www/html/}" done' sh {} + >/var/www/html/uploads/Music/songs.index
這個單一
find
命令將查找名稱與給定模式匹配的所有正常文件(即不是目錄等)的路徑名。對於這些路徑名的批次,呼叫一個簡短的內聯 shell 腳本。該腳本簡單地遍歷目前批次的路徑名並將它們列印出來,稍作修改。對路徑名的修改是通過參數替換完成的
${pathname#/var/www/html/}
。這將從 中的值的開頭刪除字元串。然後使用的格式字元串將確保這部分被替換為./var/www/html/``$pathname``printf``../
也可以看看