從 bash 腳本中無需 PATH 即可執行命令的便攜方式
cron 使用非常稀疏的
/usr/bin:/usr
. 結果,雖然像這樣的一行lvcreate --size 1G --snapshot ...
當我從終端執行腳本時工作得很好,如果從 crontab 執行它就找不到 lvcreate。這裡描述了一個類似的問題,但我對處理潛在問題的一般策略更感興趣。
到目前為止我提出的想法:
- 作為一種快速解決方法,我在腳本頂部手動設置了 PATH。我也可以在 crontab 中執行此操作。如果系統範圍的 PATH 發生變化,我可能需要手動更新所有這些行。
- 一個更持久的解決方案是在我的腳本中使用絕對路徑,例如用類似的東西替換呼叫,
/sbin/lvcreate --size 1G ...
但是雖然這可以在我第一次遇到這個問題的 Ubuntu 伺服器上工作,但在我的 Arch Linux ARM (RPi) lvcreate 位於 / usr/bin/.- 我可以
which
正確設置 PATH 的每個命令,儲存結果並在我的腳本頂部設置一個本地別名,但這對我來說似乎有點混亂。- 我考慮採購/ etc / environment。這適用於我的 Ubuntu 機器(我認為也適用於普通的 debian),但是在我的 RPi 上,系統範圍的 PATH 沒有設置在那裡。出於同樣的原因(不想依賴於各種發行版中某些文件的位置和/或使用),我對使用 .bashrc 或類似文件猶豫不決。
所以我的問題是:什麼是使腳本不依賴於設置的 PATH 並仍然保持可移植性的好方法?有沒有最先進的方法?
PATH
明確設置。如果您從腳本中執行此操作,則可以添加到 的目前設置
$PATH
,然後您將尊重那裡的任何內容,只需添加您想要確保不失去的內容:#!/bin/bash PATH=$PATH:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin ...
也許在 crontab 配置中設置會更合適
PATH
(你可以在那裡設置環境變數),因為實際上你正在解決 cron 本身的缺點,所以也許在 cron 中修復它比修改你的腳本更有意義。如果你在 cron 中設置它,你需要
PATH
完成設置,因為你不能從那裡引用它的目前值:# my user's crontab PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin 0 2 * * * /usr/local/bin/my2amjob.sh
(您可能需要稍微不同的目錄順序,這取決於您的某些系統或您自己最終是否為安裝在稍後列出的目錄中的更簡單版本安裝“覆蓋”
$PATH
,但請檢查您的系統目前設置的內容,看看是否可以調和。)希望這能解決您的問題。
如果系統範圍的 PATH 發生變化,我可能需要手動更新所有這些行。
坦率地說,我不會為此擔心太多。您的分發包將始終將其二進製文件安裝在 、 或 下
/usr/bin
,因此/usr/sbin
您將始終能夠在不更改任何路徑的情況下訪問它們。發行版長期以來認為更新以包含新目錄是一場噩夢,因此他們一直在避免這種情況,而是將符號連結或包裝腳本添加到主目錄。/bin``/sbin``$PATH``bin
對於您自己安裝的軟體,建議更新
$PATH
,我建議您也這樣做,在下面創建符號連結或包裝腳本,並儘可能/usr/local/bin
避免更改。$PATH
Linux 發行版也正在採取一些措施,使這些差異
$PATH
成為過去的問題。首先是
/usr
合併工作,它變成/bin
了指向的符號連結/usr/bin
和/sbin
指向的符號連結/usr/sbin
。所有二進製文件都安裝在/usr
(對於打包程序來說更容易),但腳本仍然通過某些絕對路徑引用它們,例如/bin/mytool
或/sbin/mytool
將繼續通過符號連結工作。這已被 Fedora 和 ArchLinux 等發行版採用,而 Debian 和 Ubuntu 等其他發行版目前正在經歷採用的步驟。ArchLinux 似乎更進了一步,它已經合併
sbin
在一起bin
了。因此,在採用合併的現代 ArchLinux 中,您可以通過四種可能的絕對路徑中的任何一種來引用二進製文件,然後您會找到它們。還有待觀察其他發行版是否也會採用第二次合併。最後,您可能需要考慮更現代的 cron 替代方案。Cron 有很多特質,比如你正在體驗的裸環境,但也使用電子郵件進行命令輸出(而不是使用日誌系統)和尷尬的命令行轉義。
您提到了 Ubuntu 和 ArchLinux,它們都支持內置的 systemd Timers,無需安裝任何軟體包。
您可能想查看 ArchLinux wiki,其中包含有關如何使用它們的優秀文章。特別是,您可能想檢查是否使用 systemd Timers 作為 cron 替代品,它具有特定的配方,可能對您的特定案例非常有用。