ð§ plistãæžãæããŠãlaunchdã¯å€ãå€ã§åãç¶ããåé¡ãèªåä¿®æ£ãã
å€§åŠæä»£ã«æ10äžãæãæã¡å¯æ¥ã§æ60äžãŸã§äŒžã°ããäŒç€Ÿéœåã®è§£éã§ãŒãã«èœã¡ãŠãå幎ã§Claude CodeèªåŸç°å¢ãçµã¿çŽãä»ã¯æå120äžã®Lilyã§ãã
ãªããã®ä»çµã¿ãå¹ãã®ã
launchdãç°å¢å€æ°ããèµ·åæã«åçµããã
SNSã®èªåããããè€æ°ã¬ãŒã³ã§èµ°ãããŠãããšããŸããããã¬ãŒã³ã®ã¿ã€ã ã¢ãŠãã30ç§ãã45ç§ã«äŒžã°ãããã~/Library/LaunchAgents/com.lily.autolike.lane1.plist ããšãã£ã¿ã§éããEnvironmentVariables ã® AUTOLIKE_TIMEOUT_SEC ã 30 ãã 45 ã«æžãæããŠä¿åããããããã§æ¬¡ã®å®è¡ããåæ ãããã¯ãã ããšæã£ãŠç»é¢ãéããã
ç¿æãã°ã確èªãããšãã¿ã€ã ã¢ãŠããšã©ãŒãæšæ¥ãšåãé »åºŠã§åºãŠããŸãã
ãã㯠launchd ã®æ ¹æ¬çãªåäœä»æ§ã«ãããã®ã§ããmacOS ã® launchd ã¯ããžã§ãã bootstrap ããç¬éã« plist ã®å
容ãèªã¿èŸŒã¿ãç°å¢å€æ°ããã®ãžã§ãã®å®çŸ©ãšããŠãåçµãããŸãããã®åŸã« plist ãã¡ã€ã«ãæžãæããŠãããã§ã«ã¡ã¢ãªäžã«ããŒããããŠãããžã§ãã®ç°å¢å€æ°ã¯äžåå€ãããŸããããã¡ã€ã«ã·ã¹ãã äžã® plist ãš launchd ãä¿æããå®è¡å®çŸ©ã®éã«ãä¹é¢ããéãã«çãŸããããã§ãã
ãã®ä¹é¢ã¯ launchctl print gui/$(id -u)/com.lily.autolike.lane1 ãå®è¡ããããšã§ç¢ºèªã§ããŸããåºåã®äžã« AUTOLIKE_TIMEOUT_SEC => 30 ãšããè¡ãæ®ã£ããŸãŸã§ããã°ãlaunchd ã¯ãŸã å€ãå€ã§åããŠããŸããplist ãã¡ã€ã«ã 45 ãæã£ãŠããŠãããžã§ã㯠30 ã§åãç¶ããŸãã
解決çã¯åçŽã§ãlaunchctl bootout ã§ãžã§ããã¢ã³ããŒãããlaunchctl bootstrap ã§å床ããŒãããã ãã§ãããããåé¡ã¯ããããã§ãã
èµ°è¡äžã®ãžã§ããæ¢ãããšããã®å®è¡åã®çµæãæ¶ãã
èªåãããã¹ã¯ãªããã1åã®å®è¡ã§ã©ãã ãã®åŠçãããããæ³åããŠãã ããã察象ã¢ã«ãŠã³ããžã®èªèšŒããã£ãŒãã®ååŸã1ä»¶ãã€ã®ãããæäœãå®äºåŸã®ãã°æžãåºãââããããé çªã«ããªã1ã€ã®ãrunãã§ãããã®éäžã§ launchctl bootout ãããããšãããã»ã¹ã匷å¶çµäºããããã® run ã§è¡ã£ããããæäœã®ææãæ¶ããŸããã¹ã¯ãªããåé ã®ã³ã¡ã³ãã«ãæèšãããŠããŸãã
# èµ°è¡äžã®ãžã§ãã bootout ãããšãã® run ã®ããããäžžããšæ¶ãããããå¿
ãåŸ
ã€ã
è€æ°ã¬ãŒã³ã24æéèµ°ãããç°å¢ã§ã¯ãããã环ç©ããŸããæå120äžã®èªåååºç€ã«ãããŠããžã§ãã1åæœ°ãããã¯åè«ã§ã¯æžãŸãªãæå€±ã§ããç¹ã«æ·±å€åž¯ã«è€æ°ã¬ãŒã³ãåæã«èµ°ã£ãŠãããšããäœã確èªããã« bootout ãçºè¡ããã¹ã¯ãªããã¯ãèªåã®ææãèªåã§åãå°é·ã«ãªããŸãã
ããšãã£ãŠãèšå®å€æŽãããæåã§æ¢ãŸã£ãŠããã®ã確èªããŠãã reload ãããã§ã¯ãèªåŸç°å¢ãšã¯åŒã¹ãŸãããæ¢ãŸã£ãŠãããã©ããããã§ãã¯ããŠãæ¢ãŸã£ãŠããã¬ãŒã³ã ãéãã«ååæããââãã®å€æãã¹ã¯ãªããã«ä»»ããã®ã autolike-plist-reconcile.sh ã®èšèšææ³ã§ãã
ãäœæ¥ãã§ãªããç°å¢ããäœããšããæè
æåãŒãããç«ãŠçŽãéçšã§åŠãã ããšããããŸãã坿¥ã§çšŒã人ã«ã¯2çš®é¡ããŸããä»äºããããªã人ããšãä»äºããããªãç¶ããç°å¢ãäœã人ãã§ãã
åè ã¯æ¯æ¥ãã°ã€ã³ããŠæãåãããæãæ¢ãããšåå ¥ãæ¢ãŸããŸããåŸè ã¯äžåºŠç°å¢ãçµãã ããšãèªåãããªããŠãåãç¶ããã·ã¹ãã ãæã¡ãŸããClaude CodeèªåŸç°å¢ãå幎ãããŠæ§ç¯ããã®ãããŸãã«ãã®çºæ³ããã§ããlaunchd ã§è€æ°ã®èªååãžã§ããåžžé§ãããèšå®ãå€ããã°ç°å¢ãèªåã§è¿œãã€ããŠããââ人ãä»å ¥ããªããŠããèšå®ãã¡ã€ã«ãšå®è¡ç¶æ ãåžžã«äžèŽãç¶ããä»çµã¿ãæã€ããšããæå120äžã®èªåŸåºç€ã®æ žã«ãªã£ãŠããŸãã
autolike-plist-reconcile.sh ã¯31è¡ã®å°ããªã¹ã¯ãªããã§ããããç°å¢ããäœããšããææ³ãåçž®ãããŠããŸããæåã§ reload ããã®ã§ã¯ãªããã¹ã¯ãªããã宿çã«ä¹é¢ãæ€ç¥ããå®å
šãªã¿ã€ãã³ã°ã ããçã£ãŠèªå修埩ãããããã¯ãèšå®å€æŽã®ãã³ã«äººãä»å
¥ããå¿
èŠããªããç°å¢ãã®ãã®ã§ãã
å šäœã®æµã
åŠçã®å šäœå
ã¹ã¯ãªãã㯠~/Library/LaunchAgents/ 以äžã® com.lily.autolike.*.plist ã1ãã¡ã€ã«ãã€åŠçããŸãã.bak-* ãš .disabled* ã®ãµãã£ãã¯ã¹ãæã€ãã¡ã€ã«ã¯ã¹ãããããæ®ã£ããã¡ã€ã«ã«ã€ã㊠plist ã®èšå®å€ãš launchd ã®å®è¡å€ãæ¯èŒããŸãã
~/Library/LaunchAgents/com.lily.autolike.*.plist
ïŒ.bak-* / .disabled* ã¯é€å€ïŒ
â
â â PlistBuddy ã§ plist ããèšå®å€ãèªã
âŒ
want=45 â plist ã«æžããŠããç®æšå€
â
â â¡ launchctl print ã§ launchd å
ã®å€ãèªã
âŒ
have=30 â launchd ãå®éã«ä¿æããŠããå€
â
ââ want == have ââââââââââââ ã¹ãããïŒå€æŽãªãïŒ
â
ââ want != have
â
â ⢠launchctl list ã§ PID ã確èª
â
ââ pid ããïŒå®è¡äžïŒ
â âââ èŠéããã°ãåºå â æ¬¡åå®è¡ãŸã§åŸ
æ©
â
ââ pid ãªãïŒåæ¢äžïŒ
âââ launchctl bootout ã§ã¢ã³ããŒã
âââ launchctl bootstrap ã§åããŒã
âââ "reloaded 30 -> 45" ããã°ã«èšé²
â plist ããç®æšå€ãèªãïŒwantïŒ
PB=/usr/libexec/PlistBuddy
want=$($PB -c "Print :EnvironmentVariables:AUTOLIKE_TIMEOUT_SEC" "$P" 2>/dev/null) || continue
PlistBuddy 㯠macOS æšæºã® plist æäœã³ãã³ãã§ãã-c "Print :EnvironmentVariables:AUTOLIKE_TIMEOUT_SEC" ã§ãã¹ãããããŒãçŽæ¥åç
§ã§ããŸãã2>/dev/null ã§ãšã©ãŒãæšãŠã|| continue ã§ãã®ããŒãæããªã plist ãã¹ãããããŸãããã® want ããplist ãã¡ã€ã«ã«æžããŠãããããããã¹ãå€ãã§ãã
â¡ launchd ãå®éã«æã£ãŠããå€ãèªãïŒhaveïŒ
D="gui/$(id -u)"
have=$(launchctl print "$D/$L" 2>/dev/null | sed -n 's/.*AUTOLIKE_TIMEOUT_SEC => \([0-9]*\).*/\1/p' | head -1)
[ -n "$have" ] || continue
launchctl print gui/501/com.lily.autolike.lane1ïŒ501ã¯UIDïŒã¯ãã®ãžã§ãã®å®å
šãªæ
å ±ãããã¹ã圢åŒã§åºåããŸãããã®äžãã sed ã§ AUTOLIKE_TIMEOUT_SEC => 30 ã®ãã¿ãŒã³ãæ¢ããæ°å€éšåïŒ30ïŒã ããæœåºããŸããhead -1 ã§è€æ°ããããé²ãã§ããŸãã
have ã空ã®å ŽåïŒãžã§ãèªäœãããŒããããŠããªãç¶æ
ïŒã¯ || continue ã§ã¹ãããããŸããããŒããããŠããªããžã§ãã«å¯Ÿã㊠bootout ã詊ã¿ããš launchctl ããšã©ãŒãè¿ãããã§ãããã® have ããlaunchd ã®ã¡ã¢ãªäžã«çŸåšååšãããå®éã«åããŠããå€ãã§ãããã¡ã€ã«ã·ã¹ãã ã§ã¯ãªã launchd ã®å
éšç¶æ
ãçŽæ¥èªãã§ããç¹ããã€ã³ãã§ãplist ãèªãã ãã§ã¯çµ¶å¯Ÿã«ããããªãå®è¡æã®å®æ
ãããã§åããŠå¯èŠåãããŸãã
⢠å€ã®æ¯èŒãš PID ãã§ãã¯
[ "$want" = "$have" ] && continue
pid=$(launchctl list | awk -v l="$L" '$3==l{print $1}')
if [ -n "$pid" ] && [ "$pid" != "-" ]; then
echo "[$(date '+%F %T')] $L å®è¡äž(pid=$pid) ã®ããèŠéã ($have -> $want)" >>"$LOG"
continue
fi
want == have ã§ããã°å€æŽäžèŠãªã®ã§ã¹ãããããŸããå·®ç°ããã£ãå Žåãæ¬¡ã« launchctl list ã§ãã®ãžã§ãã®çŸåšã® PID ã確èªããŸããlaunchctl list ã®åºå㯠PID LastStatus Label ã®3ã«ã©ã ã§ãawk ã§ã©ãã«ãäžèŽããè¡ã® PID ãåãåºããŸããPID ã -ïŒåæ¢äžã瀺ã launchd ã®æ
£äŸè¡šèšïŒã§ãªãéãããžã§ãã¯å®è¡äžãšã¿ãªããŠãèŠéãããéžæããŸãã
ãã°ã«ã¯æ¬¡ã®ãããªåœ¢åŒã§èšé²ãããŸãã
[2026-08-23 08:30:00] com.lily.autolike.lane1 å®è¡äž(pid=12345) ã®ããèŠéã (30 -> 45)
ã倿Žãããã£ããã¿ã€ãã³ã°ãåŸ ã£ãŠããããšããæå³ã次åç¢ºèªæã«ãããããŸãããã®ã¹ã¯ãªããã¯å®æå®è¡ãžã§ããšã㊠launchd ã«ç»é²ããŠãããããèŠéãã«ãªã£ãŠã次ã®èµ·åã¿ã€ãã³ã°ã§åã³ãã§ãã¯ãã空ããåºãã°èªåçã«ååæããŸãã
⣠bootout â bootstrap ã«ããååæ
launchctl bootout "$D/$L" 2>/dev/null
if launchctl bootstrap "$D" "$P" 2>/dev/null; then
echo "[$(date '+%F %T')] $L reloaded $have -> $want" >>"$LOG"; changed=$((changed+1))
else
echo "[$(date '+%F %T')] $L RELOAD FAILED" >>"$LOG"
fi
ãžã§ãã忢äžãšç¢ºèªã§ããå Žåã®ã¿ bootout â bootstrap ãå®è¡ããŸããbootout ã§äžåºŠã¢ã³ããŒãããbootstrap ã§ plist ãèªã¿çŽããŠããŒããçŽãããšã§ãAUTOLIKE_TIMEOUT_SEC ã®æ°ããå€ã launchd ã®ã¡ã¢ãªã«åã蟌ãŸããŸãã
æåæã®ãã°äŸã¯æ¬¡ã®ãšããã§ãã
[2026-08-23 08:30:05] com.lily.autolike.lane1 reloaded 30 -> 45
倿Žåã®å€ãšå€æŽåŸã®å€ã䞊ã¹ãããšã§ããäœãå€ãã£ããããäžç®ã§ããããŸãã倱æããå Žå㯠RELOAD FAILED ãšæ®ããæ¬¡åã®å®è¡ã§å詊è¡ãããŸããã¹ã¯ãªããã®æ«å°Ÿã§ã¯ã1åã®å®è¡ã§äœä»¶ã®ååæãè¡ããããããŸãšããŠãã°ã«èšé²ããŸãã
[ "$changed" -gt 0 ] && echo "[$(date '+%F %T')] done changed=$changed" >>"$LOG"
changed=0 ã®å ŽåïŒå
šã¬ãŒã³ãäžèŽããŠããå ŽåïŒã¯ãã°ãåºåããŸããããã®èšèšã«ããããã°ãã¡ã€ã«ã«ã¯ãäœããå€ãã£ãæã ããèšé²ãæ®ããæ¥åžžçãªãã€ãºãæããããŸããæ°åã®ãã°ãã¡ã€ã«ã暪æããŠç¶æ
ãææ¡ããèªåŸç°å¢ã§ã¯ããã€ãºã®ãªããã°ã¯ãããã°é床ã«çŽçµããŸãã
PATH ã®æç€ºã¯ã¹ã¯ãªããåé ã®1è¡ãæ ã£ãŠããŸãã
PATH=/usr/bin:/bin:/usr/sbin:/sbin; export PATH
launchd ã®ãžã§ããšããŠåãã¹ã¯ãªããã¯ãéåžžã®ã¿ãŒããã«ã»ãã·ã§ã³ãšã¯ç°ãªãæå°éã®å®è¡ç°å¢ã§èµ·åããŸããPATH ãæç€ºããªããš PlistBuddy ã launchctl ã®ãã¹è§£æ±ºã倱æãããæå
ã§ã¯åãã®ã« launchd ããèµ·åãããšåããªãããšããå
žåçãªæ²Œã«ã¯ãŸããŸããset -uo pipefail ãšåãããŠãæå³ããªãåäœãæåããå°ããæ§é ã«ãªã£ãŠããŸãã
å®è£ ã®è©³çް
set -uo pipefail ãå®ã3ã€ã®å£ããã
ã¹ã¯ãªããã®2è¡ç®ã¯æ¬¡ã®ãšããã§ãã
set -uo pipefail
ãã®1è¡ãæããŠããã ãã§ãã¹ã¯ãªããã¯ãäžèŠåããŠãããäœãããŠããªããç¶æ
ã«é¥ããŸãã-u ã¯æªå®çŸ©å€æ°ã®åç
§ããšã©ãŒã«ãããªãã·ã§ã³ã§ãã仮㫠$have ã®ååŸã«äœ¿ã倿°åãã©ããã§ã¿ã€ãããŠãããšããŸãã-u ãªãã®å Žåãã¿ã€ããã倿°ã¯ç©ºæååãšããŠå±éããã[ "$want" = "$have" ] ã® $have ã空ã«ãªããŸãããwant ã 45ãhave ã空æååãã¯äžèŽããªãããæ¯èŒã¯åœã«ãªããPIDãã§ãã¯ãžé²ã¿ãŸããlaunchctl list ã®åºåã«ã¯åœç¶ãã®ã©ãã«ã¯ååšããªãã®ã§ PID ãåããã[ -n "$pid" ] ã¯åœãã€ãŸãã忢äžããšèª€å€å®ã㊠bootout â bootstrap ãèµ°ããŸããäœãå£ããååæã§ããŠããŸãå ŽåããããŸãããã¿ã€ããã倿°ã®ãã©ããã空ããšããç¶æ
ãå¥ã®ããžãã¯ãçãããå¯èœæ§ã¯åžžã«æ®ããŸãã-u ã¯ãã®çš®ã®ãã°ãã·ã§ã«ããšã©ãŒã§æ¢ããããšã§æ©æçºèŠã匷å¶ããŸãã
-o pipefail ã¯ãã€ãã©ã€ã³å
šäœã®çµäºã³ãŒããå¶åŸ¡ããŸãã-o pipefail ãªãã®å Žåããã€ãã©ã€ã³ã®çµäºã³ãŒãã¯æåŸã®ã³ãã³ãã®ãã®ã«ãªããŸããã€ãŸã launchctl print "$D/$L" 2>/dev/null | sed -n '...' | head -1 ã®åºåã空ã§ãã£ãŠããhead -1 ãæ£åžžçµäºïŒçµäºã³ãŒã0ïŒã§ããã° $? ã¯0ã§ããset -e ã䜿ã£ãŠããªãæ¬ã¹ã¯ãªããã§ã¯å³åº§ã«åé¡ã«ã¯ãªããŸããããå°æ¥ãã®ã¹ã¯ãªãããæ¹å€ãããšãã« pipefail ã®æç¡ãæåãå€ããããããæåããæç€ºããŠããããšãå®å
šã§ãã
-o ãªãã®åçŽãª -uo ãšæžããŠã广ã¯åãã§ãããset -uo pipefail ãšæç€ºããããšã§ãpipefailãŸã§æå³ããŠèšå®ããããšããæå³ãèªã¿åããŸãã
glob + case ã«ããé€å€èšèš
for P in "$HOME"/Library/LaunchAgents/com.lily.autolike.*.plist; do
case "$P" in *.bak-*|*.disabled*) continue ;; esac
glob ãã¿ãŒã³ã§å¯Ÿè±¡ãã¡ã€ã«ãçµã蟌ãã ããšãããã« case ã§é€å€ãã2段æ§ãã«ãªã£ãŠããŸããé€å€ã find ã®ãªãã·ã§ã³ã glob ã®åŠå®èšæ³ã§è¡ãã case ã䜿ã£ãŠããçç±ã¯æå¿«ã§ããã·ã§ã«ã®åŠå® globïŒ!(*.bak*) ã®ãã㪠extglobïŒã¯ç§»æ€æ§ãäœããbash ãš zsh ã§ã¯æå¹åã®ãªãã·ã§ã³ãç°ãªããŸããlaunchd ããèµ·åãããã¹ã¯ãªãã㯠/bin/bash ã§åããããset ã§ extglob ãæç€ºçã«æå¹ã«ããªãéã䜿ããŸããããŸããé€å€ãã¿ãŒã³ãå¢ããå Žåã« case 㯠| ã§è¿œå ããã ãã§æžã¿ãå¯èªæ§ãä¿ãããŸãã
.bak- ã®ãµãã£ãã¯ã¹ãåé¡ã«ãªãã®ã¯ãããã¹ããšãã£ã¿ãèªåçã«äœæããããã¯ã¢ãããã¡ã€ã«ã LaunchAgents ãã£ã¬ã¯ããªå
ã«æ®ã£ãŠããŸãã±ãŒã¹ãããããã§ããcom.lily.autolike.lane1.plist.bak-20260823 ã®ãããªãã¡ã€ã«ã *.plist ã«ã¯ãããããŸãããããšãã£ã¿ã«ãã£ãŠã¯ .plist.bak 圢åŒã§ã¯ãªã .plist ã®é£ã«å¥åã§ããã¯ã¢ãããäœããã®ããããŸãã.disabled ã¯æåã§ãžã§ããç¡å¹ã«ããããšãã«ååãå€ããŠéçšããããã®èŠçŽã§ããã®é€å€ãå
¥ããŠããããšã§ launchctl unload ã䜿ããªããŠãããã®ãã¡ã€ã«ã¯ä»ã¯äœ¿ããªãããšããæå³ãäŒããããŸãã
sed ã«ãã倿œåºã®æ£ç¢ºãªåã
have=$(launchctl print "$D/$L" 2>/dev/null \
| sed -n 's/.*AUTOLIKE_TIMEOUT_SEC => \([0-9]*\).*/\1/p' \
| head -1)
launchctl print gui/501/com.lily.autolike.lane1 ã®åºåã®ãã¡ãç°å¢å€æ°ãèŒã£ãŠããéšåã¯æ¬¡ã®ãããªåœ¢åŒã§ãïŒ501 ã¯å®éã®UIDïŒã
environment = {
AUTOLIKE_TIMEOUT_SEC => 30
HOME => /Users/...
}
sed ã® s/.*AUTOLIKE_TIMEOUT_SEC => \([0-9]*\).*/\1/p ã¯ãè¡å
šäœã察象ã«ããŒåã®ååŸã .* ã§é£²ã¿èŸŒã¿ã\([0-9]*\) ã§æ°å€éšåã ãããã£ããã£ã°ã«ãŒãã«åã㊠\1 ãšããŠåºåããŸãã-n ãš p ãã©ã°ã®çµã¿åããã§ããããããè¡ã ããåºåããããããç°å¢å€æ°ãååšããªãå Žåã¯äœãåºåãããŸããã
head -1 ã§æåã®1è¡ã«çµã£ãŠããã®ã¯ããžã§ãåãä»ã®èšå®å€ã«å¶ç¶ AUTOLIKE_TIMEOUT_SEC => ã«äŒŒãæååãå«ãŸããŠããå Žåã®å€éããããé²ãããã§ããå®éã«ã¯ããåŸãŸããããé²è¡çã«1è¡ã ãåãããšã§ãè€æ°è¡ãè¿ã£ãŠããå Žåã« $have ãè€æ°è¡ã«ãªããåŸç¶ã®æ¯èŒãå
šãŠå€±æããããšããç¶æ³ãæé€ããŠããŸãã
awk ã«ãã PID æœåºãš "-" ã®æå³
pid=$(launchctl list | awk -v l="$L" '$3==l{print $1}')
if [ -n "$pid" ] && [ "$pid" != "-" ]; then
launchctl list ã®åºåã¯3ã«ã©ã ã§ãã
PID Status Label
12345 0 com.lily.autolike.lane1
- 0 com.lily.autolike.lane2
第1ã«ã©ã ã PID ã§ããžã§ããçŸåšå®è¡äžã®å Žåã¯æ°å€ãå
¥ãã忢äžïŒæ¬¡åã® StartInterval ãåŸ
ã£ãŠããç¶æ
ïŒã®å Žå㯠- ãå
¥ããŸããawk -v l="$L" '$3==l{print $1}' ã¯ç¬¬3ã«ã©ã ãã©ãã«ãšäžèŽããè¡ã®ç¬¬1ã«ã©ã ãåºåããŸãã
æ¡ä»¶å€å®ã [ -n "$pid" ] ã ãã§ã¯äžååã§ãã-n ã¯ã空æååã§ãªããããã¹ãããã®ã§ã- ãšããæååã¯é空ãšããŠçã«ãªããŸããã€ãŸããPID ã - ã®åæ¢äžãžã§ããå®è¡äžãšèª€å€å®ããŠæ°žé ã«èŠéãç¶ããããšããç¶æ
ãçºçããŸãã[ "$pid" != "-" ] ã®è¿œå ãã§ãã¯ãããã®èª€å€å®ãé²ãã§ããŸãã
bootout ã® 2>/dev/null ãæã€åªçæ§
launchctl bootout "$D/$L" 2>/dev/null
if launchctl bootstrap "$D" "$P" 2>/dev/null; then
bootout ã®è¡ã«ã¯ || exit 1 ã || continue ããããŸããã2>/dev/null ã§ãšã©ãŒãæšãŠãçµäºã³ãŒããç¡èŠããŠæ¬¡ã® bootstrap ãžé²ãèšèšã§ãã
ããã«ã¯çç±ããããŸããbootout ã¯å¯Ÿè±¡ãžã§ãããã§ã«ã¢ã³ããŒããããŠããç¶æ
ã§ãåŒã³åºãããããšããããŸãïŒä»ã®ã¹ã¯ãªãããå
ã« bootout ããå Žåãããžã§ããã¯ã©ãã·ã¥ããçŽåŸãªã©ïŒããã®ãšã launchctl bootout ã¯ãšã©ãŒãè¿ããŸãããç®çã¯ããžã§ããã¢ã³ããŒããããç¶æ
ã«ããããšãã§ããããã§ã«ã¢ã³ããŒããããŠãããªãæåãšå矩ã§ãããšã©ãŒã§æ¢ãŸããšã次㮠bootstrap ãèµ°ããã«ååæãå
šãŠå€±æããŸãã2>/dev/null ã§ãšã©ãŒãæšãŠãç¡æ¡ä»¶ã§ bootstrap ãžé²ãããšã§åªçæ§ã確ä¿ããŠããŸãã
bootstrap ã®æ¹ã¯ if ã§æåŠã確èªããŠããŸããplist ãã¡ã€ã«ã®ã·ã³ã¿ãã¯ã¹ãšã©ãŒãæš©éäžè¶³ãªã©ãbootstrap ã®å€±æã¯ãååæã«å€±æããããšããç¶æ
ç°åžžãæå³ãããããã°ã« RELOAD FAILED ãæ®ããæ¬¡åå®è¡ã§å詊è¡ããèšèšã«ããŠããŸãã
changed ã«ãŠã³ã¿ãšãã°ã®èšèšææ³
changed=0
# ... ã«ãŒãå
ã§ changed=$((changed+1)) ...
[ "$changed" -gt 0 ] && echo "[$(date '+%F %T')] done changed=$changed" >>"$LOG"
changed ã0ã®ãšãã¯ãµããªãŒè¡ãåºåããŸãããããã¯æå³çãªèšèšã§ãããã®ã¹ã¯ãªãã㯠launchd ã®å®æå®è¡ãžã§ããšããŠç»é²ãããŠããŸããå
šã¬ãŒã³ã® want == have ãäžèŽããŠããã®ãæ£åžžãªç¶æ
ã§ãããæ£åžžãªå®è¡ãæ¯åãã°ã«1è¡æ®ãã°ãæ°æ¥ã§ãã°ãæ°çŸè¡ã«ãªããŸãããç°åžžããã£ããšãã ãèšé²ãæ®ããèšèšã«ããããšã§ããã°ãã¡ã€ã«ãèŠãç¬éã«ãå€åããã£ãæ¥æãšå
容ãã ããç®ã«å
¥ããŸãã
äžæ¹ããèŠéããã¯ã«ãŒããåããã³ã«ãã°ãåºåããŸãã
echo "[$(date '+%F %T')] $L å®è¡äž(pid=$pid) ã®ããèŠéã ($have -> $want)" >>"$LOG"
ããã¯æå³çã«æ®ããŠããŸããã倿Žããã®ã«ãªãåæ ãããªãã®ããããããã°ãããšããèŠéãã®ãã°ãè€æ°è¡ç¶ããŠããã°ãå®è¡äžã®ãžã§ãããã£ãŠæ©äŒåŸ
ã¡ãããŠããããšããã«ããããŸããreloaded ãã°ãæçµçã«çŸããã°æ£åžžã«å®äºããããšã確èªã§ããRELOAD FAILED ãæ¥ãã°ç°åžžãç¥ããŸãããã°ã®å¯åºŠããããã°ã®é床ã«çŽçµããããããåžžæ verboseãã§ããåžžæ silentãã§ããªãããå€åãšåŸ
ã¡ã ããèšé²ãããèšèšãéžãã§ããŸãã
ç§ãè©°ãŸã£ã話
PIDã "-" ã®ãžã§ãããå®è¡äžããšèª€å€å®ããŠæ°žé ã«èŠéãç¶ãã
æåã«ã¹ã¯ãªãããæžãããšããPID ãã§ãã¯ã®ã³ãŒãã¯æ¬¡ã®ããã«ãªã£ãŠããŸããã
pid=$(launchctl list | awk -v l="$L" '$3==l{print $1}')
if [ -n "$pid" ]; then
echo "å®è¡äžã®ããèŠéã"
continue
fi
ãPID ã空ã§ãªããã°å®è¡äžããšããå€å®ã§ãããããç»é²ããŠ1æ¥åããããšããããã°ã«ãèŠéããã ããå»¶ã ãšç¶ããŠããŸããã
[2026-08-10 01:00:00] com.lily.autolike.lane2 å®è¡äž(pid=-) ã®ããèŠéã (30 -> 45)
[2026-08-10 02:00:00] com.lily.autolike.lane2 å®è¡äž(pid=-) ã®ããèŠéã (30 -> 45)
[2026-08-10 03:00:00] com.lily.autolike.lane2 å®è¡äž(pid=-) ã®ããèŠéã (30 -> 45)
pid=- ãšããåºåãèŠãŠæ°ã¥ããŸãããlaunchctl list ã¯åæ¢äžã®ãžã§ãã«å¯Ÿã㊠PID ã«ã©ã ã空ã«ããã®ã§ã¯ãªãã- ãšãã1æåãå
¥ããŸãã- ã¯ç©ºæååã§ã¯ãªãã®ã§ [ -n "$pid" ] ã¯åžžã«çã«ãªããã©ããªã«åŸ
ã£ãŠããå®è¡äžããšå€å®ããç¶ããŸãã
ä¿®æ£ã¯1è¡è¿œå ããã ãã§ãã
if [ -n "$pid" ] && [ "$pid" != "-" ]; then
ããã§ãPIDãååšãããã€åæ¢äžã瀺ã"-"ã§ãªãå Žåãã®ã¿å®è¡äžãšå€å®ããããã«ãªããŸãããlaunchd ã®æ
£äŸè¡šèšãç¥ããªããšçµ¶å¯Ÿã«èžãèœãšã穎ã§ãman launchctl ã«ãããã£ãšããæžããŠããŸãããå®éã® launchctl list åºåãç®ã§ç¢ºèªããŠåããŠæ°ã¥ããŸããã
PATHæªèšå®ã§PlistBuddyãèŠã€ãããå šã¹ãããããã
ã¹ã¯ãªãããã¿ãŒããã«ããæåå®è¡ãããšãã¯å®ç§ã«åããŠããŸãããåãã¹ã¯ãªããã launchd ã«ç»é²ããŠå®æå®è¡ããããšããã°ãã¡ã€ã«ãäžåæŽæ°ãããŸãããchanged ã«ãŠã³ã¿ãåããŠããªãã©ããããèŠéããã°ããåºãŠããªãã
set -uo pipefail ãããããããšã©ãŒã§æ¢ãŸã£ãŠããã¯ãã§ããå®éšã®ããã«ã¹ã¯ãªããåé ã« exec >> /tmp/debug.log 2>&1 ã远å ããŠãããã°åºåãæŸããšã次ã®ãšã©ãŒãåºãŠããŸããã
/bin/bash: /usr/libexec/PlistBuddy: No such file or directory
PlistBuddy 㯠/usr/libexec/PlistBuddy ãšãã絶察ãã¹ã䜿ã£ãŠããã®ã«ãèŠã€ãããªãââåå ã¯è¡14ã® PB=/usr/libexec/PlistBuddy ã§çµ¶å¯Ÿãã¹ãæå®ããŠããã«ããããããã$PB ã®å±éãäœããã®çç±ã§ç©ºã«ãªã£ãŠããããšã§ããã-u ãªãã·ã§ã³ã«ããç©ºå€æ°ã®åç
§ã§ãšã©ãŒã«ãªããfor ã«ãŒãã continue ã§ã¯ãªã exit ã«è¿ã圢ã§çµäºããŠããã®ã§ãã
調ã¹ããšãPB=/usr/libexec/PlistBuddy ã®åã«å¥ã®å€æ°ã§ PlistBuddy ã䜿ãããšãã詊ã¿ã®çè·¡ïŒã³ã¡ã³ãã¢ãŠããããå®ã¯ -u ã®ããã§å¥ã®åé¡ãåŒãèµ·ãããŠããïŒãæ®ã£ãŠããŸãããæŽçã®éçšã§å€æ°åç
§ãå£ããŠããããšããã®ãæ£ç¢ºãªåå ã§ãã
ãã䞊è¡ããŠçºèŠããæ¬è³ªçãªåé¡ã PATH ã§ãããlaunchd ããèµ·åãããã·ã§ã«ã¹ã¯ãªããã¯ãéåžžã®ã¿ãŒããã«ã»ãã·ã§ã³ã§èšå®ããã PATHïŒ.zshrc ã .zprofile ã§è¿œå ããã /opt/homebrew/bin çïŒãäžååŒãç¶ãããŸãããPATH=/usr/bin:/bin:/usr/sbin:/sbin ãæç€ºããªããšãã¹ã¯ãªããå
ã§äœ¿ãã³ãã³ãããæå
ã§ã¯åãã launchd ã§ã¯åããªãããšããç¶æ
ã«ãªããŸãã
PlistBuddy 㯠/usr/libexec/ ã«ãããã絶察ãã¹æå®ã® PB=/usr/libexec/PlistBuddy ã¯åé¡ãããŸããããlaunchctlãsedãawkãdate ã¯ãããã PATH çµç±ã§è§£æ±ºãããŸããlaunchd ã®æå°ç°å¢ã§ã¯ /usr/bin:/bin:/usr/sbin:/sbin ãæšæºã§ãããç°å¢ã«ãã£ãŠã¯æŽã«çãå ŽåããããŸãã2è¡ç®ã® PATH æç€ºã¯ããã®åé¡ãäžåºŠèžãã ããšäºåºŠãšèžãŸãªãããã®ä¿éºããšããŠæžããŠããŸãã
PATH=/usr/bin:/bin:/usr/sbin:/sbin; export PATH
launchctl print ã®åºåã空ã§å
šã¬ãŒã³ãã¹ãããããã
ããæãå
šã¬ãŒã³ã® have ã空ã«ãªã£ãŠããããã«ã¹ã¯ãªãããå
šã¹ãããããŠããäºè±¡ãçºçããŸããããã°ã«äœãåºãŠããªããããæ£åžžçµäºããŠãããã¹ãããããŠããããšããç¶æ
ã§ãã
launchctl print gui/501/com.lily.autolike.lane1 ãã¿ãŒããã«ã§çŽæ¥å®è¡ãããšããšã©ãŒãè¿ã£ãŠããŸããã
Could not find service "com.lily.autolike.lane1" in domain for port
launchd ã«ããŒããããŠããªããžã§ãã«å¯Ÿã㊠launchctl print ã¯ç©ºæååã§ã¯ãªããšã©ãŒãè¿ããŸãã2>/dev/null ã§ãšã©ãŒãæšãŠãŠãããã have ã¯ç©ºã«ãªãã[ -n "$have" ] || continue ã§ã¹ããããããŸãã
åå ãé¡ããšãåå€ã«å¥ã®èšå®äœæ¥ã§èª€ã£ãŠ launchctl bootout ãè€æ°ã¬ãŒã³ã«å¯ŸããŠå®è¡ããŠããŸããbootstrap ãå¿ãããŸãŸæãè¿ããŠããããšãããããŸããããžã§ãèªäœãååšããªãç¶æ
ã§ã¯ autolike-plist-reconcile.sh ã¯äœãã§ããŸããããããŒããããŠããªããžã§ããæ€ç¥ãããšãã«ã¢ã©ãŒããåºããæ©èœã¯ãã®ã¹ã¯ãªããã®ã¹ã³ãŒãå€ã§ãã
ããã¯èšèšã®éçã§ããããã°ã§ã¯ãããŸããããã®ã¹ã¯ãªããã®è²¬åã¯ãããŒãæžã¿ãžã§ãã®ç°å¢å€æ°ã®ãºã¬ãä¿®æ£ããããšãã§ããããžã§ããååšããªãå Žåã®åŸ©æ§ã¯å¥ã®ä»çµã¿ãæ ããŸããã¹ã¯ãªãããããããšãšãããªãããšãæç¢ºã«åããããšã§ã1ã€ã®åŠçãè¥å€§åããŠè€æ°ã®åé¡ã1ã€ã®ã³ãŒãã§è§£ãããšããèªæãæã¡åã£ãŠããŸãã
ããã¯ã¢ãããã¡ã€ã«ãåŠçããŠãšã©ãŒãã°ã溢ãã
ããã¹ããšãã£ã¿ã§ plist ãçŽæ¥ç·šéããŠããææã«ããšãã£ã¿ãèªåããã¯ã¢ããã ~/Library/LaunchAgents/ å
ã«äœæããŠããŸãããcom.lily.autolike.lane1.plist~ ã®ãããªåœ¢åŒã§ãïŒ~ ã¯äžéšã®ãšãã£ã¿ã䜿ãããã¯ã¢ãããµãã£ãã¯ã¹ïŒããã®ãã¡ã€ã«ã¯ glob *.plist ã«ã¯ãããããªãããåé¡ãããŸããã§ããããcom.lily.autolike.lane1.plist.bak-20260810 ãšãã圢åŒã§æ®ã£ããã¡ã€ã«ã glob ã«ãããããŠããŸããŸããã
ããã¯ã¢ãããã¡ã€ã«ã com.lily.autolike. ã§å§ãŸã .plist ã§çµãããããã¹ã¯ãªãããåŠç察象ãšå€æããŸããPlistBuddy ã§ããã¯ã¢ããã® want ãèªã¿åããlaunchctl print ã§ãžã§ãã® have ãèªã¿åããåœç¶äžèŽããŠããã®ã§ã¹ãããââãšããæµããªãåé¡ãããŸããããããã¯ã¢ãããã¡ã€ã«ã®å
容ãå€ãå€ãæã£ãŠããå Žåãããã¯ã¢ããã® want ãå®è¡äžãžã§ãã® have ãšç°ãªããäžèŠãª bootout â bootstrap ãèµ°ããŸãã
case "$P" in *.bak-*|*.disabled*) continue ;; esac ã®é€å€ãã¿ãŒã³ã¯ãã®çµéšãã远å ãããã®ã§ãããšãã£ã¿ã®èªåããã¯ã¢ããåœåèŠåã«åãã㊠.bak- ãšãããã¿ãŒã³ã«ããŠããŸãïŒ- ä»ãã«ããŠããã®ã¯ .bak åäœã§ã¯ä»ã®ã±ãŒã¹ãšæ··åããå¯èœæ§ãããããïŒãããã¯ã¢ããæŠç¥ãæã€ç°å¢ã§ã¯ããã®ãããªå¯äœçšãå
ã«æœ°ããŠããããšãèªåŸç°å¢ã®å®å®æ§ã«çŽçµããŸãã
ã€ãŸãããã€ã³ã
launchd à plist ååæã¹ã¯ãªãããèªåŸç°å¢ã«çµã¿èŸŒãéçšã§ãå®éã«èžãã èœãšã穎ãç¶²çŸ
ããŸããåæ®µã§è©³è¿°ãã4ä»¶ïŒPIDã®-誀å€å®ã»PATHæªèšå®ã»launchctl print空ã»ããã¯ã¢ãããã¡ã€ã«æ··å
¥ïŒã«å ããéç£ãã§ãŒãºã§ç¹°ãè¿ãåŒã£ããããã¿ãŒã³ãæŽçããŸããã
å®è¡ç°å¢ã»èµ·åãŸãã
- launchd ã® PATH ã¯
/usr/bin:/bin:/usr/sbin:/sbinãããªããã¿ãŒããã«ã§åããŠã launchd ããèµ·åãããšcommand not foundã«ãªããPATH=/usr/bin:/bin:/usr/sbin:/sbin; export PATHã1è¡ç®ã«æžããªããã°å§ãŸããªãã - PlistBuddy 㯠PATH çµç±ã§ã¯è§£æ±ºã§ããªãã
/usr/libexec/PlistBuddyãšãã絶察ãã¹ã§å€æ°ã«åããŠããïŒPB=/usr/libexec/PlistBuddyïŒãPATH ã«å ¥ããããšããŠã/usr/libexecã¯ããã©ã«ã PATH å€ã®ããç¡æå³ã - ã¹ã¯ãªããã«
execæš©éãä»ãå¿ãããlaunchd ã¯ProgramArgumentsã§æå®ãããã¹ãå®è¡ããããchmod +xãå¿ãããšPermission deniedã§å³æ»ããã°ã«ãäœãæ®ããªãããåå ç¹å®ãé ããã - plist ã®
ProgramãšProgramArguments[0]ãæ··åšããããProgramãæå®ãããšProgramArguments[0]ã argv[0] æ±ãã«ãªã仿§ãç¥ããã«äž¡æ¹æžããšã/bin/bashã§ã¯ãªãèªåã®ã¹ã¯ãªãããçŽæ¥æž¡ãããŠæ§æãšã©ãŒæ±ãã«ãªãã
ã©ãã«ã»ãã¡ã€ã«åœåã®äžäžèŽ
- plist ã® Label å€ãšãã¡ã€ã«åãäžèŽããŠããªãã
launchctl listã§ãã£ã«ã¿ããawk -v l="$L"ã¯$L=$(basename "$P" .plist)ããåãããããã¡ã€ã«åãš Label ãäžèŽããŠããªããã° PID ãåãããåžžã«ã忢äžããšèª€å€å®ããŠäžèŠãª bootout ãèµ°ãã - glob ãã¿ãŒã³ã«åŒã£ããããã¹ãçš plist ã眮ããŠããŸãã
com.lily.autolike.test.plistã®ãããªååã§åäœç¢ºèªçšã眮ããšæ¬çªåæ§ã«åŠçãããã.disabledãµãã£ãã¯ã¹ãä»ããŠé€å€ããèŠçŽãå®ããªããšããã¹ãçšèšå®ãæ¬çªç°å¢ãäžæžãããã - Label åã«å€§æåã»ã¹ããŒã¹ãæ··å
¥ããã
launchctl listã®ç¬¬3ã«ã©ã 㯠Label ãã®ãã®ãåºåããããããã¡ã€ã«åãšç°ãªã倧æå衚èšããããšawkã®ãããã倱æãããåœåèŠåã¯com.lily.autolike.以éãå šãŠå°æåã»ãããåºåãã§çµ±äžããã
launchctl ã®åºå仿§ãŸãã
- launchctl print ã®åºå圢åŒã macOS ããŒãžã§ã³ã§åŸ®åŠã«å€ãããmacOS 14 â 15 ã®ã¢ããã°ã¬ãŒãã§
environment = {ã®ã€ã³ãã³ããå€ãããsed ã®ãã¿ãŒã³ãäžèŽããªããªã£ãããšããããsed -n 's/.*AUTOLIKE_TIMEOUT_SEC => \([0-9]*\).*/\1/p'ã®.*ãååŸã飲ã¿èŸŒãèšèšãªã®ã§å€§åã®ã€ã³ãã³ãå€åã«ã¯èããããããŒåã®ååŸã®ã¹ããŒã¹æ°ãå€ãã£ãå Žå㯠sed ãã¿ãŒã³ã®èŠçŽããå¿ èŠã - launchctl list ããã¡ã€ã³ãè·šããšå¥ããã»ã¹ã®ã©ãã«ãæ··åšãããè€æ°ãŠãŒã¶ãŒã§ãã°ã€ã³ããŠããç°å¢ã§ã¯ãä»ãŠãŒã¶ãŒã®ãžã§ãã
launchctl listã«æ··å ¥ããå Žåããããã©ãã«åãcom.lily.ã§å§ããããšã§å®å®³ã¯åºã«ããããawkã®ããããäºæããªãã©ãã«ã«åå¿ããªãããå®å šäžèŽïŒ$3==lïŒã䜿ãã®ãåæã launchctl printã«æž¡ã domain+label ã®åœ¢åŒãééãããgui/$(id -u)/com.lily.autolike.lane1ã¯æ£ãããuser/$(id -u)/âŠãšæžããšå¥ãã¡ã€ã³ãæããD="gui/$(id -u)"ã倿°åããŠäžç®æã ã管çããããšã§ãtypo ãã¹ã¯ãªããå šäœã«äŒæãããªã¹ã¯ãæ¶ãã
ç°å¢å€æ°ãŸãã
- ç£èŠå¯Ÿè±¡ã®ããŒå
AUTOLIKE_TIMEOUT_SECãã¹ã¯ãªããã«è€æ°ç®æã«æžããŠããŸããwant ååŸã® PlistBuddy ã³ãã³ãïŒ14è¡ç®ïŒãš have ååŸã® sed ãã¿ãŒã³ïŒ15è¡ç®ïŒã®2ç®æãåºãŠãããå°æ¥ããŒåã倿Žãããšãçæ¹ã ãçŽãäºæ ãé²ãããã倿°åããŠ1ç®æã«éçŽããã®ãå®å šã - æŽæ°å€ä»¥å€ãå
¥ã£ããšãã« sed ã®
\([0-9]*\)ããããããªããAUTOLIKE_TIMEOUT_SECã®å€ã45sã®ããã«åäœä»ãã§æžãããŠãããš[0-9]*ã空ã«ãªããPlistBuddy ã® want ååŸãš sed ã® have ååŸã§å€ã®åãé£ãéããç°ãªãæååãšããŠåžžã«å·®ç°ãããšèª€å€å®ãããŠæ¯å bootout ãèµ°ããå€ã¯çŽç²ãªæŽæ°ã§ç®¡çããã EnvironmentVariablesããŒã plist ã«ååšããªãã$PB -c "Print :EnvironmentVariables:AUTOLIKE_TIMEOUT_SEC" "$P" 2>/dev/null || continueã®|| continueããã®ã±ãŒã¹ãåŠçãããã2>/dev/nullãå€ããŠãããã°ãããšãDoes Not Existããšã©ãŒãåºãŠåå ãåãããæ²é»ããããã«ããŠãããããå šã¹ããããããŠããã°ã«äœãæ®ããªãç¹ã«æ³šæããã
ãã°ã»èšºæãŸãã
- ãã°ãã£ã¬ã¯ããªãååšããªãã
LOG="$HOME/.claude/logs/autolike-plist-reconcile.log"ã®ãã£ã¬ã¯ããªïŒ~/.claude/logs/ïŒãæªäœæã ãšecho ⊠>>"$LOG"ããšã©ãŒã«ãªããset -uo pipefailã®-uã§ã¯ãªãæžã蟌ã¿ãšã©ãŒã§ã¹ã¯ãªãããæ»ã¬ãplist ã«ç»é²ããåã«mkdir -p ~/.claude/logsãå®è¡ããŠããã - changed=0 ãç¶ãããšããæ£åžžããšåãéãããå
šã¬ãŒã³ã
want == haveã§äžèŽããŠãããªãæ£åžžã ããhave ã空ïŒãžã§ãæªããŒãïŒã§å šã¹ããããããŠããå Žåã changed=0 ãã€ãã°ç¡åºåã«ãªãã宿çã«launchctl list | grep com.lily.autolikeã§å šã¬ãŒã³ãããŒãæžã¿ããå¥ç³»çµ±ã§ç¢ºèªããã - èŠéããã°ãæ¯æéç¶ããŠããåé¡ãªãããšæŸçœ®ããŠããŸããé·æéãžã§ããçµãããªãå Žåãplist ã®å€æŽãæ°žä¹ ã«åæ ãããªãããšã«ãªããèŠéãã N æéç¶ããå Žåã«ã¢ã©ãŒããåºãä»çµã¿ãæããªããªããå°ãªããšã鱿¬¡ã§ãã°ãç®èŠç¢ºèªããç¿æ £ãæã€ã
PID ãã§ãã¯ã®å¢ç
- PID ãåãããããã®ããã»ã¹ãæ¢ã« zombie ã«ãªã£ãŠãããmacOS ã® launchd ã¯ã¯ã©ãã·ã¥ããããã»ã¹ãããã«ååããããå®çšäžã¯çšã ãã
launchctl listã« PID ãæ®ã£ãŠããã®ã«å®ããã»ã¹ãååšããªãã¿ã€ãã³ã°ãããããã®ãšã bootout ã¯æåããããèµ°è¡äžãæ¢ããã圢跡ããã°ã«æ®ããªããããåŸãããããã°ãã«ããã - StartInterval ãé·ããžã§ãã®ã¿ä¿æããç°å¢ã§ãæ°žé ã«ç©ºããæ¥ãªãããšé¯èŠãããStartInterval 3600ïŒ1æéïŒã®ãžã§ãã¯1æéã«1åããå®è¡ãããªããããPID ã
-ã«ãªãã®ãçæéã ããreconcile ã¹ã¯ãªããèªèº«ãçãééïŒäŸ: 5åïŒã§å®æå®è¡ãããŠããã°æ¬¡ã®æ©äŒã«æãããããéã«ãã®ãžã§ãã®å®è¡æéã StartInterval ãšåçšåºŠã«é·ããã°ãå®è³ªçã«åžžæå®è¡äžã®ç¶æ ã«ãªãååæã®æ©äŒãæ°žä¹ ã«æ¥ãªãã
ãã¹ããã©ã¯ãã£ã¹
å®éã®éçšã§ããããæåãããã£ãŠããã°ããã£ãããšæããã«ãŒã«ãæŽçããŸãã31è¡ã®ã¹ã¯ãªããã«è©°ã蟌ãŸããèšèšææ³ããåçŸå¯èœãªåœ¢ã§æžãåºããŸããã
â PATH ã1è¡ç®ã«åºå®ãã
PATH=/usr/bin:/bin:/usr/sbin:/sbin; export PATH
ã¿ãŒããã«ã§åäœç¢ºèªããŠã宿ããšæã蟌ãã®ãæå€§ã®çœ ã§ããlaunchd çµç±ã®å®è¡ã¯ PATH ãæå°ç°å¢ããæããã.zshrc ã .zprofile ã®èšå®ã¯äžååŒãç¶ããŸãããPATH ãå
é è¡ã§åºå®ããããšã§ãæå
ã§ã¯åããlaunchdã§ã¯åããªããåé¡ãæ§é çã«æé€ã§ããŸãã
â¡ set -uo pipefail ãåžžã«æžã
set -uo pipefail
-u ãæªå®çŸ©å€æ°ãå³ãšã©ãŒã«ããpipefail ããã€ãã©ã€ã³éäžã®å€±æãçµäºã³ãŒãã«äŒæãããŸãããã®1è¡ããªããã°ã倿°åã®ã¿ã€ããéäžã®ã³ãã³ã倱æããäœããªãã£ãããã«ãééããwrong ãªç¶æ
ã§åŠçãç¶è¡ããŸããã·ã§ã«ã¹ã¯ãªããã®å®å
šè£
眮ãšããŠäŸå€ãªãæžãã
⢠PlistBuddy ã¯çµ¶å¯Ÿãã¹ã§å€æ°åãã
PB=/usr/libexec/PlistBuddy
PATH çµç±ã§ã¯è§£æ±ºã§ããªããããã¹ã¯ãªããåé ã§å€æ°ã«åããŠãããŸããè€æ°ç®æã§äœ¿ãå Žåã倿°åç §1æ¬ã«çµ±äžããããšã§ããã¹ãå€ãã£ããšãã«1è¡ä¿®æ£ã§æžã¿ãŸãã
⣠launchd ã®ãã¡ã€ã³æå®ã倿°åãã
D="gui/$(id -u)"
gui/UID ãšãã圢åŒãæ¯åã€ã³ã©ã€ã³ã§æžããš typo ãªã¹ã¯ãäžãããŸãã倿°1ã€ã«ãŸãšããã° launchctl print "$D/$L" ãš launchctl bootout "$D/$L" ãš launchctl bootstrap "$D" "$P" ã®å
šãŠã1ç®æã®å€æŽã§è¿œåŸããŸãã
†é€å€ãã¿ãŒã³ã¯ case ã§ç®¡çãã
case "$P" in *.bak-*|*.disabled*) continue ;; esac
extglob ãåŠå® glob ã«é Œãããcase ã§é€å€ããèšèšãæãç§»æ€æ§ãé«ãã§ããé€å€ãã¿ãŒã³ãå¢ããå Žåã | ã§è¿œèšããã ãããšãã£ã¿ã®ããã¯ã¢ããåœåèŠåã«åãã㊠.bak-ïŒãã€ãã³ä»ãïŒã«ããããšã§ .bak åäœã®èª€ããããé²ããŸãã
⥠want ãš have ã®ååŸã¯ã倱æãããã¹ãããããæç€ºãã
want=$($PB -c "Print :EnvironmentVariables:AUTOLIKE_TIMEOUT_SEC" "$P" 2>/dev/null) || continue
have=$(launchctl print "$D/$L" 2>/dev/null | sed -n '...' | head -1)
[ -n "$have" ] || continue
want ã®ååŸå€±æïŒããŒãååšããªã plistïŒã¯ || continue ã§å³ã¹ããããhave ã®ååŸå€±æïŒãžã§ãæªããŒãïŒã¯ç©ºæååãã§ãã¯ã§ã¹ãããã2çš®é¡ã®å€±æãã¿ãŒã³ãç°ãªãææ³ã§åŠçããŠããçç±ã¯ãPlistBuddy ã¯å€±ææã«é0çµäºã³ãŒããè¿ãã®ã«å¯Ÿããlaunchctl print ã®ãã€ãã¯å
šäœãšããŠ0çµäºã«ãªãããããã§ãã
⊠PID ã® - ãæç€ºçã«ã忢äžããšå€å®ãã
if [ -n "$pid" ] && [ "$pid" != "-" ]; then
launchctl list ã¯åæ¢äžã®ãžã§ãã«æ°å€ PID ã§ã¯ãªãæåå - ãå
¥ããŸãã-n ãã¹ãã ãã§ã¯ - ããPIDããããšèª€å€å®ããŠæ°žé ã«èŠéãç¶ããŸãã[ "$pid" != "-" ] ãå¿
ã远å ãããman launchctl ã«æèšãããŠããªããããå®éã®åºåãç®ã§èŠããŸã§æ°ã¥ããªãèœãšã穎ã§ãã
â§ bootout ã¯åªçã«ã»bootstrap ã ãæåŠã確èªãã
launchctl bootout "$D/$L" 2>/dev/null
if launchctl bootstrap "$D" "$P" 2>/dev/null; then
âŠ; changed=$((changed+1))
else
echo "⊠RELOAD FAILED" >>"$LOG"
fi
bootout ã¯ãã§ã«ã¢ã³ããŒãæžã¿ã®ç¶æ
ã§ãåŒã³åºãããŸãããšã©ãŒã§æ¢ãŸããšç¶ã bootstrap ãèµ°ããååæãå
šãŠå€±æããŸãã2>/dev/null ã§ãšã©ãŒãæšãŠãç¡æ¡ä»¶ã§ bootstrap ãžé²ãããšã§åªçæ§ã確ä¿ãbootstrap ã®æåŠã ãããã°ã«èšé²ããŠæ¬¡åå®è¡ã§å詊è¡ãããŸãã
âš ãã°ã¯ãå€åãšåŸ ã¡ã ããèšé²ãã
# èŠéã â æ¯åèšé²ããïŒãããã°ã®ããïŒ
echo "[$(date '+%F %T')] $L å®è¡äž(pid=$pid) ã®ããèŠéã ($have -> $want)" >>"$LOG"
# 倿Žãªã â èšé²ããªã
# 倿Žãã â èšé²ãã
[ "$changed" -gt 0 ] && echo "[$(date '+%F %T')] done changed=$changed" >>"$LOG"
å
šãŠæ£åžžãªå®è¡ã¯ silent ã«ãããèŠéãã¯ã倿Žããã®ã«åæ ãããªãããããã°ã«å¿
èŠãªã®ã§æ®ããreloaded ãš RELOAD FAILED ã¯ç¶æ
å€åãªã®ã§å¿
ãæ®ãããã®3段éã«ããããã°ãéããç¬éã«ãäœããã£ããã©ãããã1è¡ã§å€æã§ããŸãã
â© ã¹ã¯ãªããã®è²¬åã1ã€ã«çµã
ãã®ã¹ã¯ãªãããè¡ãã®ã¯ãããŒãæžã¿ãžã§ãã®ç°å¢å€æ°ã®ãºã¬ãä¿®æ£ããããšãã ãã§ããããžã§ããæªããŒããªãèªåã§ããŒããããã倱æãç¶ãããSlackéç¥ãéããããã°ãå§çž®ã»ããŒããŒã·ã§ã³ããããšãã£ãæ©èœã¯æã¡ãŸããã責åã1ã€ã«çµãããšã§ããã¹ãã容æã«ãªããä»ã®ã¹ã¯ãªãããšçµã¿åããããããªããŸããã¢ã©ãŒããå¿ èŠãªãå¥ã¹ã¯ãªããã«åãåºãã
⪠ç£èŠå¯Ÿè±¡ããŒåã1ç®æã§ç®¡çãã
AUTOLIKE_TIMEOUT_SEC ãšããããŒåã PlistBuddy ã³ãã³ããš sed ãã¿ãŒã³ã®2ç®æã«åºãŠããŸããå°æ¥çã«ç£èŠå¯Ÿè±¡ã远å ã»å€æŽããå Žåã«åãã倿°åããŠäžéšã«å®çŸ©ããŠãããšä¿å®æ§ãäžãããŸãã
KEY=AUTOLIKE_TIMEOUT_SEC
want=$($PB -c "Print :EnvironmentVariables:$KEY" "$P" 2>/dev/null) || continue
have=$(launchctl print "$D/$L" 2>/dev/null | sed -n "s/.*$KEY => \\([0-9]*\\).*/\\1/p" | head -1)
çŸè¡ã®31è¡ã¹ã¯ãªããã¯ã·ã³ã°ã«ãã¡ã€ã«ã»ã·ã³ã°ã«ããŒçšéãšããŠå®çµããŠãããã倿°åããŠããŸããããè€æ°ç°å¢å€æ°ãç£èŠããå Žåã¯ã«ãŒãã«å±éããŸãã
â« å®æå®è¡ã®ééã¯ã蚱容ã§ããåæ é å»¶ãããéç®ãã
reconcile ã¹ã¯ãªããèªèº«ã launchd ã«ç»é²ãããšãã® StartInterval ã¯ããplist ãæžãæããŠããç°å¢å€æ°ãå®éã«åæ ããããŸã§ã®æå€§åŸ
ã¡æéãã«ãªããŸãã5å以å
ã®åæ ãæåŸ
ãããªã StartInterval 300 ã§ç»é²ããŸãããã ãå®è¡äžã®ãžã§ããèŠéãã±ãŒã¹ããããããå®éã®åæ é
å»¶ã¯ãreconcile ã®éé + ãžã§ãã®æå€§å®è¡æéããäžéã§ãã
⬠ãã°ãã¡ã€ã«ã®å Žæã launchd ã® StandardOutPath ãšæããªã
launchd ã® StandardOutPath ãš StandardErrorPath 㯠plist ã§æå®ãã stdout/stderr ã®ãªãã€ã¬ã¯ãå
ã§ããreconcile ã¹ã¯ãªããèªèº«ã®ã¢ããªã±ãŒã·ã§ã³ãã°ïŒLOG 倿°ã§æã ~/.claude/logs/autolike-plist-reconcile.logïŒã¯ãããšã¯å¥ã«ç®¡çããŸããäž¡è
ãåããã¡ã€ã«ãæããšãlaunchd ã®ã·ã¹ãã ã¡ãã»ãŒãžãšã¢ããªãã°ãæ··åšããŠè§£æãå°é£ã«ãªããŸãã
â ãã¹ãå®è¡ã¯ bash -x ã§
launchd ã«ç»é²ããåã«åäœç¢ºèªãããšãã¯ãbash -x ã§ã³ãã³ãããã¬ãŒã¹åºåããªããå®è¡ããŸãã
bash -x ~/.claude/scripts/autolike-plist-reconcile.sh
åè¡ã®å®éã®å±éå€ã + ä»ãã§åºåãããããã倿°ãæåŸ
ã©ããå±éãããŠããããlaunchctl print ã®åºåã sed ã«ãã¡ããšæž¡ã£ãŠããããç®èŠç¢ºèªã§ããŸããæå
ã§åäœã確èªããŠãã plist ã«ç»é²ããããšã§ãæ²é»ãã°ïŒãã°ãåºãã«äœãããªãç¶æ
ïŒãæªç¶ã«é²ããŸãã
â® exit 0 ã§æç€ºçã«æ£åžžçµäºããã
exit 0
ã¹ã¯ãªããã®æ«å°Ÿã« exit 0 ã眮ãããšã§ãlaunchd ã«å¿
ãæ£åžžçµäºã³ãŒããè¿ããŸããKeepAlive ãªã©ã®èšå®ãšçµã¿åããããšããé0çµäºããžã§ããäºæããªãåèµ·åã«ãŒãã«èªå°ããã±ãŒã¹ãé²ããŸããæåŸã®ã³ãã³ãã [ "$changed" -gt 0 ] && ⊠ã®åœ¢åŒã ãšãæ¡ä»¶ãåœã®å Žåã« && å
šäœãåœïŒçµäºã³ãŒã1ïŒãè¿ããããæç€ºç㪠exit 0 ãå¿
èŠã§ãã
ãŸãšã
autolike-plist-reconcile.sh ããã£ãŠããããšãäžèšã§èšãã°ããlaunchd ã®ã¡ã¢ãªäžã®å€ããã¡ã€ã«ã·ã¹ãã ã® plist ãšå®æçã«æ¯èŒãããžã§ããæ¢ãŸã£ãŠãããšãã ãéãã«ååæãããã§ãã
å ·äœçã«ã¯æ¬¡ã®4ã¹ãããã§ãã
PlistBuddyã§ plist ã®ç®æšå€ïŒwantïŒãèªãlaunchctl printã§ launchd ã®å®è¡å€ïŒhaveïŒãèªã- å·®ç°ãããå Žåã
launchctl listã® PID ã確èªãã - PID ã
-ïŒåæ¢äžïŒãªãbootoutâbootstrapã§ååæãPID ãæ°å€ïŒå®è¡äžïŒãªãèŠéã£ãŠãã°ã ãæ®ã
ãã®ãèµ°è¡äžã¯èŠéãã»ç©ºããåŸ ã€ãèšèšã«ãããå®è¡äžã®èªååãžã§ããäžæããã«èšå®ãåæ ã§ããŸããæåã§ reload ã¿ã€ãã³ã°ãèŠèšããå¿ èŠããªããreconcile ã¹ã¯ãªããèªèº«ã launchd ã«ç»é²ããŠããã°æ¬¡ã®åæ¢ã¿ã€ãã³ã°ã§èªåçã«åŠçãããŸãã
ãã€ã³ãã¯èšèšã®æœãã§ãã31è¡ã®ã¹ã¯ãªãããæ ãã®ã¯ãããŒãæžã¿ãžã§ãã®ãºã¬ä¿®æ£ãã ãã§ããžã§ãèµ·åã»ã¢ã©ãŒãã»ãã°ããŒããŒã·ã§ã³ã¯æã¡ãŸããã1ã¹ã¯ãªãã1責åãèªåŸç°å¢ã®åºæ¬ã§ããè€æ°ã®ãžã§ãã24æéåãç¶ããç°å¢ã§ã¯ããå£ãããæ°ã¥ãããããå£ããªãä»çµã¿ãäœããã»ããé·æçãªã¡ã³ããã³ã¹ã³ã¹ããå§åçã«äœãã§ãã
æå120äžã®èªåŸåºç€ã¯ããããããå°å³ã ãã©ç¢ºå®ã«æ©èœãã31è¡ãã®ç©ã¿éãã§ã§ããŠããŸããæŽŸæãªæ©èœã¯1ã€ããããŸãããlaunchd ã®ä»æ§ãæ£ç¢ºã«ææ¡ãã倱æãã¿ãŒã³ãå ã«æœ°ãããã°èšèšãäžå¯§ã«ããââãã®ç¹°ãè¿ããã人ãããªããŠãåãç¶ããç°å¢ããäœããŸãã
ä»çµã¿ã®å šäœåã»æ120äžã®å èš³ã»30æ¥æé ã¯æænoteã«ãŸãšããŠããŸãã ð Claude CodeèªåŸç°å¢ã§ãå®éã©ã皌ãã â ä»çµã¿ã»å®äŸã»å§ãæ¹ã»ãµããŒã
LilyïŒ@bokuwalilyïŒâ å人éçºè ãClaude Code ã§èªåååºç€ãçµã¿ãªãããiOSã¢ããªãWebãµãŒãã¹ãéç£ããŠããŸã
- AIã§ãå¯ãŠãŠãåãä»çµã¿ããäœã£ãŠæ120äžã«ãã話㯠noteã®ææèšäº ã«ð°
- OSS: github.com/bokuwalily ð
- ææ°æ å ±ã»ãåãåãã㯠X @bokuwalily ãžð
- AIå°å ¥ã»èªååã®çžè«ãšå®è£ ãã³ãã¬7æ¬ã®é åžã¯ å ¬åŒLINE ããð¬
çããã® â€ïž ãã·ã§ã¢ãå±ã¿ã«ãªããŸãïŒ