Skip to content

Instantly share code, notes, and snippets.

@donaldguy
Last active February 1, 2024 06:56
Show Gist options
  • Save donaldguy/ebf7957ec4bb8db0669c137d82934389 to your computer and use it in GitHub Desktop.
Save donaldguy/ebf7957ec4bb8db0669c137d82934389 to your computer and use it in GitHub Desktop.
boot messages during `podman machine start` (qemu)
#!/bin/bash
set -o errexit -o nounset -o pipefail
bootstrap_podman() {
if ! podman system info &>/dev/null; then
echo "!!podman not initialized: doing that" >&2
if ! podman machine inspect &>/dev/null; then
podman machine init --user-mode-networking
fi
if [[ -z "$(podman machine inspect --format='{{ .State }}')" ]]; then
podman_machine_start_but_with_boot_logs
fi
else
echo "Podman VM looks good to go"
fi
}
podman_machine_start_but_with_boot_logs() {
declare podman_machine_console_log_file
patch_podman_vm_qemu_config_to_log_boot_messages
local tailer_cmd
local podman_start_pid
local watcher_pid
tailer_cmd="$(if [[ -t 0 ]]; then echo "less -R +F"; else echo "tail -F"; fi)"
rm -f "$podman_machine_console_log_file"
set -m
podman machine start &
podman_start_pid=$!
echo "About to start streaming console logs... (will auto-exit when reaches login prompt)"
file_existance_busychecker "$podman_machine_console_log_file"
podman_machine_boot_messages_tail_busywatcher "$$" "$tailer_cmd" "$podman_machine_console_log_file" &
watcher_pid=$!
$tailer_cmd "$podman_machine_console_log_file" || :
if ! wait $watcher_pid; then
kill "$podman_start_pid"
die "You didn't wait for the machine to finish booting before killing the log viewer"
else
echo "... and now we wail a little more"
fi
wait "$podman_start_pid"
}
patch_podman_vm_qemu_config_to_log_boot_messages() {
local podman_machine_config
local pmc_dirname
local pmc_basename
podman_machine_config="$(podman machine inspect --format='{{ .ConfigPath.Path }}')"
pmc_dirname="$(dirname "$podman_machine_config")"
pmc_basename="$(basename "${podman_machine_config}" .json)"
podman_machine_console_log_file="${pmc_dirname}/${pmc_basename}-console.log"
local chatty_params=()
local script_add_chatty_params
chatty_params+=('-chardev')
chatty_params+=("socket,id=char-console,path=${podman_machine_console_log_file/.log/.sock},server=on,wait=off,logfile=${podman_machine_console_log_file}")
chatty_params+=('-serial')
chatty_params+=('chardev:char-console')
# shellcheck disable=SC2059
printf -v script_add_chatty_params "$(cat <<-'EOS'
jq \\
\t'if .CmdLine[-1] == $ARGS.positional[-1] then . else .CmdLine += $ARGS.positional end' \\
\t%s.json \\
\t --args -- \\
%s
\t> %s.json.chatty
EOS
)" "$pmc_basename" "$(printf '\t\t"%s" \\\n' "${chatty_params[@]}")" "$pmc_basename"
cd "$pmc_dirname"
bash -c "$script_add_chatty_params"
mv "${pmc_basename}.json.chatty" "${pmc_basename}.json"
cd -
}
file_existance_busychecker() {
local file
file=$1
while true; do
if [[ -f "$file" ]]; then
return 0
fi
sleep 3
done
}
podman_machine_boot_messages_tail_busywatcher() {
local ppid
local tailer_cmd
local tailer_pid
local file
ppid="$1"
# shellcheck disable=SC2206
tailer_cmd=( $2 )
file="$3"
set +e
while true; do
if [[ -z "${tailer_pid:-}" ]]; then
tailer_pid=$(pgrep -P "$ppid" "${tailer_cmd[0]}")
else
if ! kill -0 "$tailer_pid" 2>/dev/null; then
return 1
fi
fi
if tail -1 "$file" | grep -q '^localhost login:'; then
[[ -n "${tailer_pid:-}" ]] && kill "$tailer_pid"
return 0
fi
sleep 2
done
}
bootstrap_podman
@donaldguy
Copy link
Author

donaldguy commented Feb 1, 2024

If for some reason you want to use this script and care, consider it under the MIT License

Copyright 2024 Donald Guy

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Not how laws/licenses generally work, but informally speaking I'mma say I have no plans to be picky about that their single condition. ... but the all caps part, yeah; I'm not gonna sue you, you don't sue me, deal? 🤝

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment