Linux命令中的“引數列表過長”錯誤
概述
在本文中,我們將討論在您嘗試在 Linux 系統上執行命令時顯示的錯誤訊息,該訊息顯示為“引數列表過長”。此錯誤可能由多種原因造成。在本篇文章中,我將解釋導致此錯誤的原因以及如何解決它。
什麼是“引數列表過長”錯誤?
此錯誤是由於向程式或 shell 指令碼傳遞了無效的引數而發生的。這意味著程式允許的引數數量超過了限制。例如,如果您執行以下命令:
ls -l /usr/bin/* | grep binutils
您可能會收到以下錯誤:
-bash: /usr/bin/grep: Argument list too long
如果您想知道上述命令失敗的原因,請繼續閱讀。
導致錯誤的原因是什麼?
我們將研究一個目錄中有很多檔案的情況。
$ ls -lrt | wc -l 230086 $ ls -lrt | tail -5 -rw-r--r-- 1 shubh shubh 0 Nov 30 14:02 events2120038.log -rw-r--r-- 1 shubh shubh 0 Nov 30 14:02 events2120040.log -rw-r--r-- 1 shubh shubh 0 Nov 30 14:02 events2120039.log -rw-r--r-- 1 shubh shubh 0 Nov 30 14:02 events2120042.log -rw-r--r-- 1 shubh shubh 0 Nov 30 14:02 events2120041.log
我們的資料夾中有超過 230K 個日誌檔名。讓我們看看我們能否獲得以單詞“events”開頭的檔案數量。
$ ls -lrt events* | wc -l -bash: /usr/bin/ls: Argument list too long 0
值得注意的是,命令失敗,並以“引數列表過長”為由。讓我們嘗試使用 rm 命令來刪除這些檔案:
$ rm -rf events*.log -bash: /usr/bin/rm: Argument list too long
該命令再次因為同樣的原因失敗。
在執行檔名擴充套件時,Bash 執行一個稱為“擴充套件”的操作,這意味著它將 * 字元與每個匹配的檔名擴充套件。結果,Bash 建立了一個非常長的引數字串,它無法處理。
如果作為命令列引數擴充套件的檔案過多,Bash 可能無法處理它們。請注意,此緩衝區(引數緩衝區)與環境變數資訊共享,因此實際可用記憶體小於此緩衝區。
之前的示例中的 rmdir(刪除目錄)命令擴充套件為:
$ rm -rf events2120038.log events2120040.log ... events0000001.log
這裡,引數向量變得比檔案中的行數更多。為避免參數過多,我們使用 getcwd() 函式獲取當前工作目錄(從檔案系統根目錄到我們當前位置的路徑)。然後,我們使用 getargs() 函式從檔案的每一行提取第一個引數。最後,我們使用 strlen() 函式確定結果字串的長度。
$ getconf ARG_MAX 2097152
ARG_max 引數確定 exec() 函式所需的最大空間。它允許核心知道執行程式所需的最大緩衝區。您可以使用 xargs 命令驗證這些限制。
$ xargs --show-limits Your environment variables take up 2504 bytes POSIX upper limit on argument length (this system): 2092600 POSIX smallest allowable upper limit on argument length (all systems): 4096 Maximum length of command we could actually use: 2090096 Size of command buffer we are actually using: 131072 Maximum parallelism (--max-procs must be no greater): 2147483647
關於引數長度上限最重要的一點是,它們在不同的作業系統之間可能有所不同。
克服限制
我們將研究解決此問題的不同方法。所有這些方法都涉及避免參數擴充套件。
使用find命令
您可以使用 find 命令迭代檔名,並使用 exec 選項或 xargs 命令逐個執行它們。
$ find . -iname "events*" | xargs ls -lrt | wc -l 230085
我們首先使用 find 命令獲取包含字串“events”的檔名。接下來,我們將 find 命令的輸出傳遞給 xargs 命令。最後,我們對 xargs 命令的結果執行 ls 和 wc 命令。
使用for迴圈方法
您可以使用另一種方法透過 for 迴圈迭代檔案。
$ for f in events*; do echo "$f"; done | wc -l 230085
這是解決此問題的幾個簡單解決方案之一。它可能比其他方法花費更長時間,但它效果很好。
手動分割
我們可以將檔案分割成更小的塊,並使用不同的字串集作為引數在每次迭代中重複執行命令。
$ ls -lrt events1*.log | wc -l 31154 $ ls -lrt events2*.log | wc -l 15941
我們只過濾名稱以“events1”開頭的檔案。在這種特定情況下,我們保持在 ARG_MAX 變數設定的限制範圍內。
然後,我們對以“event1”、“event2”等開頭的檔案重複相同的步驟。
當我們只需要刪除目錄的內容時
如果我們嘗試從目錄中刪除所有檔案,那麼考慮一下我們無法做到這一點的情況:
$ rm -rf * -bash: /usr/bin/rm: Argument list too long
如果我們想解決這個問題,我們可以改為刪除目錄並重新建立它。
$ rm -rf /home/shubh/tempdir/logs_archive $ cd home/shubh/tempdir && mkdir logs_archive
這裡,logs_archive 資料夾包含我們要刪除的檔案。
由於我們正在刪除資料夾並重新建立它,因此這種方法不會保留資料夾的原始許可權設定或所有權。
結論
我們研究了幾種處理“過長”問題的方法。
我們首先討論了導致此問題的原因,然後研究了一些解決方法。
資料結構
網路
關係資料庫管理系統 (RDBMS)
作業系統
Java
iOS
HTML
CSS
Android
Python
C語言程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP