1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
# sysconfig — Misc one-time boot configuration (grab-bag)
[service]
name = "sysconfig"
description = "Misc boot config: core, dump, keymap, scheduler, rctl, tmp cleanup"
type = "oneshot"
[exec]
start = "/etc/zyginit/services/sysconfig/start.sh"
[dependencies]
requires = ["filesystem"]
[restart]
on = "never"
#!/bin/zsh
# sysconfig — misc one-time boot configuration
#
# Each command is deliberately wrapped in || true for commands where a
# specific failure (no device present, no config file, etc.) is acceptable.
# A truly mandatory setting would be its own service.
# Use absolute paths for every external command — first-boot-of-fresh-deploy
# can transiently fail bare-command lookups under I/O pressure (devfsadm +
# reconfigure + parallel service start). See [[zyginit-service-empty-path]]
# for the investigation that disproved the original "empty PATH" theory.
#
# The remaining failure mode for this script (sysconfig exit=-1 still
# observed on 2026-06-08 fresh-deploy boots, with an empty service log)
# is suspected to be inside coreadm/dumpadm/dispadmin/rctladm: they
# exec() internal helpers that themselves do PATH-based lookup, and if
# any of those misses, the parent hangs and zyginit eventually SIGKILLs
# the oneshot (-> exit=-1). Diagnostic markers below pin down which
# command was running when zyginit's timeout fired.
PATH=/usr/sbin:/usr/bin:/sbin:/bin
export PATH
set -u
# Note: NOT using set -e — individual failures are handled per-command.
# --- Diagnostic step markers ------------------------------------------
# zyginit captures stderr to /var/log/zyginit/sysconfig.log. Emit a
# timestamped marker before and after each suspect command so the LAST
# marker in the log identifies the hang point on a fresh-deploy failure.
# Cheap: ~14 lines on a happy-path boot.
# Builtin `print` resolves at shell startup (no external lookup); /bin/date
# is an absolute external path so it can't lose to a transient PATH race.
mark() { print -r -- ">>> $(/bin/date +%T.%N) $*" >&2; }
# Core files: enable per-process pattern, apply config from /etc/coreadm.conf
mark "coreadm --init"
/usr/bin/coreadm --init 2>/dev/null || true
mark "coreadm done"
# Crash dump: use configured dump device (set once per system, may be a zvol)
mark "dumpadm -u"
/sbin/dumpadm -u 2>/dev/null || true
mark "dumpadm done"
# Keyboard map: -i reads layout from /etc/default/kbd (non-interactive).
# -s would prompt the operator at the console, blocking boot.
if [[ -x /usr/bin/kbd ]]; then
mark "kbd -i"
/usr/bin/kbd -i 2>/dev/null || true
mark "kbd done"
fi
# Scheduler default dispatch table (TS = time-share, usual default)
mark "dispadmin -d TS"
/usr/sbin/dispadmin -d TS 2>/dev/null || true
mark "dispadmin done"
# Resource controls (/etc/project-based rctls) — reload into kernel
if [[ -x /usr/sbin/rctladm ]]; then
mark "rctladm -u"
/usr/sbin/rctladm -u 2>/dev/null || true
mark "rctladm done"
fi
# Clean up /tmp on boot (tmpfs is usually empty after reboot but defend)
if [[ -d /tmp ]]; then
mark "tmp cleanup"
/usr/bin/find /tmp -mindepth 1 -maxdepth 1 -exec /bin/rm -rf {} + 2>/dev/null || true
mark "tmp cleanup done"
fi
# rpcbind needs /var/run/rpc_door (mode 1777) to exist before it starts
# (matches the SMF rpc-bind method). Create it here so it's ready by the
# time tier 4 brings up rpcbind.
mark "rpc_door"
/bin/mkdir -p /var/run/rpc_door
/bin/chmod 1777 /var/run/rpc_door
mark "exit 0"
exit 0
|