Bash

CWD 和文件路徑字元串在 launchctl 呼叫中自動連接

  • September 8, 2019

我目前正在嘗試為我的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]看看你是否達到了預期的效果

  1. 您在 == 之前和之後需要空格

$$ [ … $$] 測試,否則它們只是被評估為字元串,並且非空總是正確的。 例如:

$ 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
  1. 您的腳本中還有一些地方$缺少 before 變數。例如
if [[ $instruction=="restart" || instruction=="unload" ]]

這需要在第二個之前和之後== 以及之前的空格:$``instruction

if [[ $instruction == "restart" || $instruction == "unload" ]]

同樣在這裡:

if [[ instruction=="restart" ]]

那應該是:

if [[ $instruction == "restart" ]]
  1. 使用變數時需要雙引號(和 shell 位置參數)。例如
local lineno="$1"
local msg="$2"

和:

instruction="$1"
filepath="$2"

和:

launchctl stop "$filepath"
launchctl unload "$filepath"
  1. 為什麼要把它寫成一個函式而不是一個獨立的腳本?你需要它來改變目前shell的環境嗎?

編寫函式沒有任何問題,但除非您希望它更改目前 shell 的環境,否則最好使用單獨的腳本提供的隔離,這樣您就不會意外更改環境。

或者將所有函式變數(包括$instruction$filepath)聲明為,local但這僅有助於防止更改變數,函式仍然可以更改其他內容,例如 shell 的目前目錄。

引用自:https://unix.stackexchange.com/questions/539558