CWD 和文件路徑字元串在 launchctl 呼叫中自動連接
我目前正在嘗試為我的bash 配置文件編寫一個函式,該函式會導致作為參數傳遞的 OSX LaunchAgent 重新啟動。這可能有點毫無意義,但對於一個我想停止為
launchctl un/load
除了對launchctl的最後呼叫之外,我幾乎已經完成了所有工作。這是函式腳本和隨之而來的錯誤消息:
功能
launchctl_mgr() { failure() { local lineno=$1 local msg=$2 echo "Failed at $lineno: $msg" } trap 'failure ${lineno} "$BASH_COMMAND"' ERR trap 'trap - ERR' RETURN instruction=$1 filepath=$2; #test whether the file argument is already a file or not and whether or not it is actually$ if [[ ! -f $2 ]] then if [[ -f ~/Library/LaunchAgents/$2.plist ]] then filepath="~/Library/Launchagents/$filepath.plist" echo "found!: $filepath" elif [[ -f /Library/LaunchAgents/$2.plist ]] then filepath="/Library/LaunchAgents/$filepath.plist" else echo "debug: ~/Library/LaunchAgents/$filepath.plist" echo "Filename supplied was not valid as a launchagent" return 1 fi fi if [[ $instruction=="restart" || instruction=="unload" ]] then echo "instruction is $instruction" echo "filepath is $filepath" launchctl stop $filepath launchctl unload $filepath if [[ instruction=="restart" ]] then launchctl load $filepath launchctl start $filepath fi fi }
輸出/錯誤
____________________ => launchctl_mgr unload local.unminimise found!: ~/Library/Launchagents/local.unminimise.plist instruction is unload filepath is ~/Library/Launchagents/local.unminimise.plist Failed at launchctl stop $filepath: /Users/[current_user]/~/Library/Launchagents/local.unminimise.plist: No such file or directory /Users/[current_user]/~/Library/Launchagents/local.unminimise.plist: No such file or directory Failed at launchctl start $filepath:
('
$$ current_user $$’ 替換我的實際使用者帳戶名) 正如您在launchctl 中看到的那樣,無論是bash 還是launchctl,目前目錄路徑和我提供給launchctl 的路徑字元串都連接在一起,從而導致錯誤。文件路徑字元串被列印出來,並且在之前的行中看起來沒問題
非常感謝 Cas 的回答和對 bash 語法的幫助,但我從一些修補中發現,波浪號是
~/Library/LaunchAgents/[agent]
導致腳本按預期工作而不拋出連接路徑的問題的原因。由於某種原因,波浪號在 launchctl 地址參數中沒有得到擴展,因此如果其他人遇到此問題,請使用:
$HOME/Library/LaunchAgents/[agent]
在 launchctl 命令中定址您的代理。
此路徑如*“遺留命令”*下所述,然後“載入”
**注意:**至少對於我的腳本來說,這實際上並不能解決 launchctl 拋出錯誤,但可以修復功能。儘管文件說:
由於先前實現中的錯誤以及長期以來客戶對這些錯誤的期望,載入和解除安裝子命令將僅由於使用不當而返回非零退出程式碼。否則,總是返回零。
..我設置的 ERR 陷阱始終拋出沒有消息的錯誤,即使腳本按預期工作並且手動複製命令不會給出任何錯誤消息。
也許有人可以彌補我的無知,但如果你在我的建議後仍然摸不著頭腦,試著
launchctl list | grep [agent_name]
看看你是否達到了預期的效果
- 您在 == 之前和之後需要空格
$$ [ … $$] 測試,否則它們只是被評估為字元串,並且非空總是正確的。 例如:
$ instruction=whatever $ [[ $instruction=="restart" ]] && echo true || echo false true
這相當於:
$ [[ whatever=="restart" ]] && echo true || echo false true
它也等價於以下(以及其他幾個變體):
$ [[ -n 'whatever=="restart"' ]] && echo true || echo false true
在所有這些情況下,您都不會檢查是否
$instruction
等於“重新啟動”。相反,您正在測試字元串whatever=="restart"
是否為非空。該字元串恰好包含字元序列==
,但這並不重要。嵌入在字元串中,它們只是沒有特殊含義的字元。與之比較:
$ instruction=whatever $ [[ $instruction == "restart" ]] && echo true || echo false false $ instruction=restart $ [[ $instruction == "restart" ]] && echo true || echo false true
- 您的腳本中還有一些地方
$
缺少 before 變數。例如if [[ $instruction=="restart" || instruction=="unload" ]]
這需要在第二個之前和之後
==
以及之前的空格:$``instruction
if [[ $instruction == "restart" || $instruction == "unload" ]]
同樣在這裡:
if [[ instruction=="restart" ]]
那應該是:
if [[ $instruction == "restart" ]]
- 使用變數時需要雙引號(和 shell 位置參數)。例如
local lineno="$1" local msg="$2"
和:
instruction="$1" filepath="$2"
和:
launchctl stop "$filepath" launchctl unload "$filepath"
- 為什麼要把它寫成一個函式而不是一個獨立的腳本?你需要它來改變目前shell的環境嗎?
編寫函式沒有任何問題,但除非您希望它更改目前 shell 的環境,否則最好使用單獨的腳本提供的隔離,這樣您就不會意外更改環境。
或者將所有函式變數(包括
$instruction
和$filepath
)聲明為,local
但這僅有助於防止更改變數,函式仍然可以更改其他內容,例如 shell 的目前目錄。