diff --git a/docker-compose.yml b/docker-compose.yml index 88cdf91..3525131 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,6 +42,11 @@ services: # If unset -> 256 RAM_COUNT: 256 + # User command or script to run after OpenWrt is booted + # Please note that all commands and script will be executed as root + #OPENWRT_AFTER_BOOT_CMD: "cat /etc/banner" + #OPENWRT_AFTER_BOOT_CMD: "/usr/bin/fw_wan_open_http" + #DEBUG: "y" ports: diff --git a/src/helpers.sh b/src/helpers.sh index 1b5e526..4603798 100644 --- a/src/helpers.sh +++ b/src/helpers.sh @@ -15,5 +15,6 @@ trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR : "${USB_1:=""}" # USB 1 vendor and device ID : "${USB_2:=""}" # USB 2 vendor and device ID : "${FORWARD_LUCI:=""}" # Make LuCI OpenWrt web interface accessible via host LAN +: "${OPENWRT_AFTER_BOOT_CMD:=""}" # User command or script to run after OpenWrt is booted : "${IS_U_OS_APP:=""}" # By default this container is not a u-OS app : "${DEBUG:="N"}" # Disable debugging diff --git a/src/init_container.sh b/src/init_container.sh index d8ef742..1011f42 100644 --- a/src/init_container.sh +++ b/src/init_container.sh @@ -74,9 +74,19 @@ else LUCI_COMMAND="sh -c 'sleep infinity'" # TODO: Find something better. Multirun needs something to run. fi +# ******* OpenWrt run command after boot handling ******* +if [[ -z "${OPENWRT_AFTER_BOOT_CMD}" ]]; then + OPENWRT_MULTIRUN_CMD="sh -c 'sleep infinity'" # TODO: Find something better. Multirun needs something to run. +else + info "Invoke command \"${OPENWRT_AFTER_BOOT_CMD}\" into OpenWrt after it is booted" + OPENWRT_MULTIRUN_CMD="/run/run_command_after_openwrt_boot.sh \"${OPENWRT_AFTER_BOOT_CMD}\"" +fi + + # Start processes exec multirun \ "qemu-openwrt-web-backend" \ "nginx" \ "/run/run_openwrt.sh" \ - "$LUCI_COMMAND" + "$LUCI_COMMAND" \ + "$OPENWRT_MULTIRUN_CMD" diff --git a/src/qemu_qmp.sh b/src/qemu_qmp.sh index 5ecbe9a..d4903bd 100644 --- a/src/qemu_qmp.sh +++ b/src/qemu_qmp.sh @@ -1,5 +1,20 @@ #!/bin/sh -# Source: https://www.redhat.com/sysadmin/arguments-options-bash-scripts +# +# Copyright Albrecht Lohofener 2025 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + VERSION=0.1 @@ -28,7 +43,7 @@ Help() # Process the input options. Add options as needed. # ############################################################ # Get the options -while getopts ":hvrqsSVR" option; do +while getopts ":hvrqsSVRc" option; do case $option in h) # display Help Help @@ -54,6 +69,29 @@ while getopts ":hvrqsSVR" option; do R) # Reboot, package qemu-ga needs to be installed echo -ne '{"execute": "guest-exec", "arguments": { "path": "reboot"}}' | nc -w 1 -U /run/qga.sock exit;; + c) # Run shell command inside OpenWrt, package qemu-ga needs to be installed + # Execute command in OpenWrt + INPUT_DATA=`echo "$2" | base64` + RETURN_JSON=`echo '{"execute": "guest-exec", "arguments": { "path": "/bin/sh", "input-data": "'${INPUT_DATA}'", "capture-output": true }}' | nc -w 1 -U /run/qga.sock` + PID=`echo $RETURN_JSON | sed -n 's/.*"pid": \([0-9]*\).*/\1/p'` # Process return and extract PID + #echo >&2 "PID: $PID" + [ -z "$PID" ] && exit 1 + while true; do # Wait for command exit + RETURN_JSON=`echo '{"execute": "guest-exec-status", "arguments": { "pid": '${PID}'}}' | nc -w 1 -U /run/qga.sock` + export EXITCODE=`echo $RETURN_JSON | sed -n 's/.*"exitcode": \([0-9]*\).*/\1/p'` + export OUT_DATA=`echo $RETURN_JSON | sed -n 's/.*"out-data": "\([^"]*\).*/\1/p' | base64 -d` + export EXITED=`echo $RETURN_JSON | sed -n 's/.*"exited": \(true\|false\).*/\1/p'` + if [ "$EXITED" = "true" ]; then + break + fi + sleep 1 + done + echo "$OUT_DATA" # Return stdout + if [ -z "$EXITCODE" ]; then # Exit code handling + exit 1 + else + exit "$EXITCODE" + fi;; \?) # Invalid option echo "Error: Invalid option" Help diff --git a/src/run_command_after_openwrt_boot.sh b/src/run_command_after_openwrt_boot.sh new file mode 100644 index 0000000..ac6b969 --- /dev/null +++ b/src/run_command_after_openwrt_boot.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# +# Copyright Albrecht Lohofener 2025 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Display help page +show_help() { + echo "Usage: $0 " + echo "" + echo "This script checks if OpenWrt is booted." + echo "Once successful, it executes the user command." + echo "" + echo "Options:" + echo " -h, --help Show this help message and exit." + exit 0 +} + +# Check for help flag +if [[ $1 == "-h" || $1 == "--help" ]]; then + show_help +fi + +# Polling the initial command until it succeeds +set +e # Enable that the next command can fail +while true; do + # Check if OpenWrt is booted + /run/qemu_qmp.sh -c 'logread | grep "procd: - init complete"' >/dev/null 2>&1 + if [ $? -eq 0 ]; then + echo "Detected OpenWrt is booted" + break + fi + + # Wait for a short time before polling again + sleep 2 + #echo "Waiting for OpenWrt boot..." +done +set -e # Revert set +e + +# Execute the second command with the argument provided as input +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +# Run user command +echo "Run command \"$1\"" +/run/qemu_qmp.sh -c "$1" + +# Never exit because multirun will exit the container then +sleep infinity \ No newline at end of file