126 lines
3.6 KiB
Bash
126 lines
3.6 KiB
Bash
# Move shell into its own systemd scope if possible
|
|
if ! hash busctl &>/dev/null; then
|
|
return
|
|
fi
|
|
if [[ $_scope_loaded == 1 ]]; then
|
|
# shell reload, ignore
|
|
return
|
|
fi
|
|
|
|
_scope_loaded=1
|
|
|
|
# Load new scope unit
|
|
busctl -q --user call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager StartTransientUnit 'ssa(sv)a(sa(sv))' \
|
|
"zsh-$$.scope" \
|
|
replace \
|
|
2 \
|
|
PIDs au 1 $$ \
|
|
Slice s app-shell.slice \
|
|
0 \
|
|
&>/dev/null # this call fails on a shell re-exec, but we don't really care since the scope will already exist in that case, so forward to dave null
|
|
|
|
# Set and unset variables
|
|
export INVOCATION_ID=$(systemctl --user show "zsh-$$.scope" | awk -F= '/InvocationID=/{ print $2 }')
|
|
export SYSTEMD_UNIT="zsh-$$.scope"
|
|
unset SYSTEMD_EXEC_PID
|
|
unset JOURNAL_STREAM
|
|
unset MEMORY_PRESSURE_WATCH
|
|
unset MEMORY_PRESSURE_WRITE
|
|
|
|
|
|
function lift-constraints() {
|
|
# Don't lift the PID constraint since there's really no reason a shell should have more than 100 active PIDs. Reap what you sow!
|
|
env systemctl --user set-property zsh-$$.scope CPUQuota=
|
|
env systemctl --user set-property zsh-$$.scope MemoryHigh=
|
|
env systemctl --user set-property zsh-$$.scope MemoryMax=
|
|
}
|
|
|
|
function detach() {
|
|
local args slice type unit passed_envs
|
|
passed_envs=(SUDO_PROMPT EDITOR SUDO_EDITOR VISUAL)
|
|
args=(--user --same-dir -q --collect)
|
|
slice="app-shell.slice"
|
|
type="scope"
|
|
while true; do
|
|
case $1 in
|
|
--help)
|
|
cat <<EOF
|
|
Usage: detach [OPTIONS] <COMMAND> [ARGS...]
|
|
|
|
Invoke a command outside of the shell's execution context, detaching it from any resource
|
|
constraints on the shell itself.
|
|
|
|
It will be run by the user service manager using systemd-run. By default, the command
|
|
is invoked in the app-shells slice, so is still subject to any restrictions placed
|
|
on the set of all user shells.
|
|
|
|
This is intended to simplify the act of intentionally launching resource-intensive programs
|
|
(such as compilers) while still limiting most programs in terms of how much they are allowed
|
|
to consume.
|
|
|
|
Some environment variables are inherited by default, which can be disabled with --clean-env:
|
|
$passed_envs
|
|
|
|
OPTIONS:
|
|
--help - display this help message and exit
|
|
--app - launch in the main app slice rather than the app-shell slice. Equivalent to --slice app.slice
|
|
--background - launch in the background slice. Equivalent to --slice background.slice
|
|
--slice <SLICE> - launch in the specified user slice.
|
|
--service - create a service unit, rather than a scope, producing a truly clean environment. This separates
|
|
the program from the shell's process tree, preventing the shell's job management from managing it.
|
|
--env <VAR>[=VALUE] - inherit the given environment variable from the shell, or set it if a value is given.
|
|
--clean-env - disable the default set of inherited environment variables
|
|
EOF
|
|
return 0
|
|
;;
|
|
--app)
|
|
slice="app.slice"
|
|
;;
|
|
--background)
|
|
slice="background.slice"
|
|
;;
|
|
--slice)
|
|
slice=$2
|
|
shift
|
|
;;
|
|
--service)
|
|
type="service"
|
|
;;
|
|
--env)
|
|
args+="-E"
|
|
args+=$2
|
|
shift
|
|
;;
|
|
--clean-env)
|
|
passed_envs=()
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
for env in $passed_envs; do
|
|
args+="--setenv=$env"
|
|
done
|
|
case $type in
|
|
service)
|
|
unit="invoke-$$@$RANDOM.service"
|
|
args+=(--service-type=exec --pty --pipe --wait)
|
|
;;
|
|
scope)
|
|
unit="invoke-$$-$RANDOM.scope"
|
|
args+="--scope"
|
|
;;
|
|
esac
|
|
systemd-run $args --slice=${slice} --unit=${unit} -- "$@"
|
|
}
|
|
|
|
for cmd in $always_detach; do
|
|
eval $(echo alias $cmd=\"detach $cmd\")
|
|
done
|
|
|
|
for cmd in $always_detach_as_service; do
|
|
eval $(echo alias $cmd=\"detach --service $cmd\")
|
|
done
|