diff --git a/scripts/host-only/wkdev-create b/scripts/host-only/wkdev-create index 73fa697..cf263d9 100755 --- a/scripts/host-only/wkdev-create +++ b/scripts/host-only/wkdev-create @@ -420,13 +420,13 @@ build_podman_create_arguments() { arguments+=("--mount" "type=bind,source=${XDG_RUNTIME_DIR},destination=/host/run,bind-propagation=rslave") # Disable SELinux isolation. - arguments+=("--security-opt label=disable") + arguments+=("--security-opt" "label=disable") # Allow for unprivileged user namespaces (bwrap) to work. - arguments+=("--security-opt unmask=ALL") + arguments+=("--security-opt" "unmask=ALL") # Required for rr to work. - arguments+=("--security-opt seccomp=unconfined") + arguments+=("--security-opt" "seccomp=unconfined") # Always set XDG_RUNTIME_DIR to the same value. arguments+=("--env" "XDG_RUNTIME_DIR=/run/user/${host_user_id}") @@ -705,21 +705,26 @@ run() { _log_ "-> Creating container '${container_name}'..." if argsparse_is_option_set "verbose"; then _log_ "" - _log_ " $ podman ${podman_arguments[@]} create ${podman_create_arguments[@]}" + _log_ " $ $(shjoin podman "${podman_arguments[@]}" create "${podman_create_arguments[@]}")" fi - container_id=$(run_podman ${podman_arguments[@]} create ${podman_create_arguments[@]}) + container_id=$(run_podman "${podman_arguments[@]}" create "${podman_create_arguments[@]}") [ -z "${container_id}" ] && _abort_ "Container creation failed - please check the logs and report any issue" _log_ "" _log_ "-> Starting container '${container_name}'..." - + local args=() if argsparse_is_option_set "attach"; then - run_podman_silent_unless_verbose start --attach "${container_id}" + args=(start --attach "${container_id}") else _log_ " NOTE: Use \`podman logs -f ${container_name}\` to follow the initialization." - run_podman_silent start "${container_id}" + args=(start "${container_id}") + fi + if argsparse_is_option_set "verbose"; then + _log_ "" + _log_ " $ $(shjoin podman "${args[@]}")" fi + run_podman_silent_unless_verbose_or_abort "${args[@]}" _log_ "" _log_ "-> Finished creation of container '${container_name}'!" diff --git a/scripts/host-only/wkdev-enter b/scripts/host-only/wkdev-enter index c79f595..e5385d9 100755 --- a/scripts/host-only/wkdev-enter +++ b/scripts/host-only/wkdev-enter @@ -91,7 +91,9 @@ ensure_container_is_running() { _log_ ""; _log_ "-> Container '${container_name}' is not yet running. Starting it before attempting to enter..."; host_setup_prerun_tasks - run_podman_silent start "${container_name}" + # There is no flag to prevent `podman start` from writing the id of the + # container to stdout, so we just connect stdout to /dev/null. + run_podman_silent_unless_verbose_or_abort start "${container_name}" >/dev/null } } diff --git a/utilities/application.sh b/utilities/application.sh index 71b0f19..b12a020 100644 --- a/utilities/application.sh +++ b/utilities/application.sh @@ -101,6 +101,60 @@ run_command_silent_unless_verbose() { fi } +# Runs a command, exiting if the command return non-zero. +# If the verbose option is enabled, stdout and stderr are connected to the screen. +# If the verbose option is not enabled, stderr is captured and printed only +# if the subprocess exits with failure. +run_command_silent_unless_verbose_or_abort() { + + local command="${1}" + shift + + local cmd_args=("${command}" "${@}") + + if argsparse_is_option_set "verbose"; then + "${cmd_args[@]}" + local code=$? + else + # We need to split the variable declaration from the variable + # assignation, as otherwise $? will not reflect the exit code of the + # subshell command: https://stackoverflow.com/a/2556122/1777162 + local captured_stderr + captured_stderr="$("${cmd_args[@]}" 2>&1 >/dev/null)" + local code=$? + fi + + if [ "${code}" -ne 0 ]; then + if ! argsparse_is_option_set "verbose"; then + echo "${captured_stderr}" >&2 + fi + _abort_ "Command failed with code ${code}: $(shjoin "${cmd_args[@]}")" + fi +} + +# Python's shlex.join(), but for Bash: receives any number of arguments +# representing a shell command invocation and echoes in return one single string +# that a user can paste in a terminal to run that command invocation. +# +# Bash provides a very similar mechanism with "${array[*]Q}", but it quotes +# even when unnecessary, which is often undesirable for user output. +shjoin() { + + local is_first=true + for arg in "$@"; do + if [[ "$is_first" == true ]]; then + is_first=false + else + echo -n " " + fi + if [[ "'${arg}'" == "${arg@Q}" ]]; then + printf "%s" "${arg}" + else + printf "%s" "${arg@Q}" + fi + done +} + init_application() { # Bash script recommendations, see https://www.davidpashley.com/articles/writing-robust-shell-scripts/. diff --git a/utilities/podman.sh b/utilities/podman.sh index fdc1d33..9ab7aa9 100644 --- a/utilities/podman.sh +++ b/utilities/podman.sh @@ -20,6 +20,7 @@ verify_podman_is_acceptable "${podman_executable}" run_podman() { run_command "${podman_executable}" "${@}"; } run_podman_silent() { run_command_silent "${podman_executable}" "${@}"; } run_podman_silent_unless_verbose() { run_command_silent_unless_verbose "${podman_executable}" "${@}"; } +run_podman_silent_unless_verbose_or_abort() { run_command_silent_unless_verbose_or_abort "${podman_executable}" "${@}"; } run_podman_in_background_and_log_to_file() {