diff --git a/AOK_VARS b/AOK_VARS index a114ffd9..de47376e 100644 --- a/AOK_VARS +++ b/AOK_VARS @@ -25,7 +25,7 @@ # Label for AOK builds, is also displayed by motd to indicate what # AOK FS release is being used # -AOK_VERSION="0.18" +AOK_VERSION="0.19" # # If defined this will be created as a no-password sudo capable user @@ -133,36 +133,23 @@ USER_SHELL="/bin/bash" # ALPINE_VERSION defines what Alpine release (minirootfs) will be used # current releases can be found at: https://alpinelinux.org/releases/ # -# ALPINE_VERSION=3.15.11 # End of Alpine support 2023-11-01 -# ALPINE_VERSION=3.16.9 # End of Alpine support 2024-05-23 -# ALPINE_VERSION=3.17.8 # End of Alpine support 2024-11-22 -# ALPINE_VERSION=3.18.7 # End of Alpine support 2025-05-09 - -# As of 2024-07-02 sudo insta-crashes iSH if using Alpine >= 3.19... +# sudo insta-crashes iSH if using Alpine >= 3.19... last checked 2024-07-02 # test: sudo ls # AOK installs an older sudo (Alpine 3.14) on such releases, this # solves the issue - +# +# ALPINE_VERSION=3.17.8 # End of Alpine support 2024-11-22 +# ALPINE_VERSION=3.18.7 # End of Alpine support 2025-05-09 # ALPINE_VERSION=3.19.2 # End of Alpine support 2025-11-01 ALPINE_VERSION=3.20.1 # End of Alpine support 2026-04-01 # # For edge releases - Current development tree # Format is the isodate featured in the minirootfs filename -# Meaning that: alpine-minirootfs-20230901-x86.tar.gz -# Would be requested as: ALPINE_VERSION="20230901" -# -# ALPINE_VERSION="20230901" # 3.19_alpha20230901 -# ALPINE_VERSION="20230329" # 3.18_alpha20230329 -# ALPINE_VERSION="20221110" # 3.17_alpha20221110 -# -# If you need to detect if the build is an edge release in your -# .AOK_VARS, when making config desicions, -# you can check it thus: +# Meaning that: alpine-minirootfs-20240606-x86.tar.gz +# Would be requested as: ALPINE_VERSION="20240606" # -# if echo "$ALPINE_VERSION" | grep -Eq '^[0-9]{8}$'; then -# echo "this is edge" -# fi +# ALPINE_VERSION="20240606" # 3.21.0_alpha20240606 # # @@ -174,7 +161,7 @@ ALPINE_VERSION=3.20.1 # End of Alpine support 2026-04-01 # # Always installed packages # -pkgs_tools="busybox-extras coreutils procps util-linux +pkgs_tools="busybox-extras coreutils util-linux sudo shadow shadow-login tzdata findutils sed tar pigz file gawk grep htop less sqlite fzf py3-pip ncdu" pkgs_shells="bash zsh" @@ -223,7 +210,7 @@ NODEJS_APKS='nodejs nodejs-dev' # not development related man pages, those doing development are # assumed to know what man pages they might need :) # -DOCS_APKS="man-db man-pages busybox-doc coreutils-doc procps-ng-doc \ +DOCS_APKS="man-db man-pages busybox-doc coreutils-doc \ sudo-doc shadow-doc shadow-login-doc tzdata-doc findutils-doc sed-doc \ tar-doc file-doc gawk-doc grep-doc htop-doc less-doc git-doc \ sqlite-doc fzf-doc py3-pip-doc ncdu-doc bash-doc zsh-doc openrc-doc \ diff --git a/Alpine/etc/motd_template b/Alpine/etc/motd_template index 04e56e47..ceca3bd2 100644 --- a/Alpine/etc/motd_template +++ b/Alpine/etc/motd_template @@ -17,3 +17,4 @@ Check ]8;;https://github.com/ish-app/ish\GitHub]8;;\ for more information, or ask on the ]8;;https://discord.gg/HFAXj44\Discord]8;;\ if you have questions. + diff --git a/Alpine/setup_alpine.sh b/Alpine/setup_alpine.sh index 907fa838..7052c3a3 100755 --- a/Alpine/setup_alpine.sh +++ b/Alpine/setup_alpine.sh @@ -39,20 +39,22 @@ handle_apks() { if ! min_release "3.16"; then if [ -z "${CORE_APKS##*shadow-login*}" ]; then - # This package was introduced starting with Alpine 3.16 - msg_3 "Excluding not yet available apk 'shadow-login" + msg_2 "Excluding packages not yet availabe before 3.16" removing_unwanted_package "shadow-login" + removing_unwanted_package "py3-pendulum" + removing_unwanted_package "zsh-completions" + removing_unwanted_package "zsh-history-substring-search" fi fi - if ! min_release 3.18; then - msg_3 "Pre 3.18 procps was called procps-ng" - CORE_APKS="$(echo "$CORE_APKS" | sed 's/procps/procps-ng/')" + #if ! min_release 3.15; then + # msg_2 "Pre 3.15 procps was called procps-ng" + # CORE_APKS="$(echo "$CORE_APKS" | sed 's/procps/procps-ng/')" # elif min_release "3.19"; then # msg_3 "Alpine >= 3.19 - procps cant be used" # removing_unwanted_package procps - fi + #fi if min_release "3.20"; then - msg_3 "Alpine >= 3.20 - coreutils cant be used" + msg_2 "Alpine >= 3.20 - coreutils cant be used" removing_unwanted_package coreutils fi @@ -136,7 +138,7 @@ prepare_env_etc() { msg_2 "Adding apk repository - testing" # cp /opt/AOK/Alpine/etc/repositories-edge /etc/apk/repositories echo "$testing_repo" >>/etc/apk/repositories - elif min_release 3.17; then + elif min_release 3.19; then # # Only works for fairly recent releases, otherwise dependencies won't # work. diff --git a/Alpine/usr_local_bin/aok-groups b/Alpine/usr_local_bin/aok-groups index 7ec21bc0..69d37942 100755 --- a/Alpine/usr_local_bin/aok-groups +++ b/Alpine/usr_local_bin/aok-groups @@ -77,11 +77,8 @@ pkg_handling() { # # Some packages change depending on Alpine release # - if ! min_release 3.18; then - packages="$(echo "$packages" | sed 's/procps-ng/procps/')" - if ! min_release 3.16; then - packages="$(echo "$packages" | sed 's/shadow-login-doc//')" - fi + if ! min_release 3.16; then + packages="$(echo "$packages" | sed 's/shadow-login-doc//')" fi # shellcheck disable=SC2086 # in this case it should expand diff --git a/Alpine/usr_local_sbin/update-motd b/Alpine/usr_local_sbin/update-motd index 441ee40d..42343825 100755 --- a/Alpine/usr_local_sbin/update-motd +++ b/Alpine/usr_local_sbin/update-motd @@ -38,23 +38,23 @@ f_obsolete="/etc/aok-release" mv "$f_obsolete" "$f_aok_fs_release" } -rm -f "$f_motd" - # create initial LF -echo >>"$f_motd" - -if [ -e "$f_aok_fs_release" ]; then - echo "AOK-FS release: $(cat "$f_aok_fs_release")" >>"$f_motd" -fi - -( - echo "Alpine release: $alp_rel" - echo "iSH release: $ish_rel" - echo -) >>"$f_motd" +echo >"$f_motd" if [ -f "$f_motd_template" ]; then cat "$f_motd_template" >>"$f_motd" fi +/usr/local/bin/aok-versions >>"$f_motd" + +#if [ -e "$f_aok_fs_release" ]; then +# echo "AOK-FS release: $(cat "$f_aok_fs_release")" >>"$f_motd" +#fi + +#( +# echo "Alpine release: $alp_rel" +# echo "iSH release: $ish_rel" +# echo +#) >>"$f_motd" + /usr/local/bin/logger update-motd updated /etc/motd diff --git a/CHANGES.md b/CHANGES.md index 91f48657..2f4e4e62 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,17 @@ I will try to keep track of changes between releases here -## Upcomming release, available in main branch +## Upcomming release, available in devel branch + +## 0.19 + +- simplified dest selection for wall +- better check if pigz is installed +- reshuffle of motd tasks +- added tools: aok_fs-save & aok_fs-replace +- updated skel files +- improved package selection for old releases +- added uptime -l to just show sysload ## 0.18 diff --git a/Debian/etc/update-motd.d/25-deb-vers b/Debian/etc/update-motd.d/25-deb-vers new file mode 100755 index 00000000..814cc69f --- /dev/null +++ b/Debian/etc/update-motd.d/25-deb-vers @@ -0,0 +1,12 @@ +#!/bin/sh +# +# Part of https://github.com/jaclu/AOK-Filesystem-Tools +# +# License: MIT +# +# Copyright (c) 2024: Jacob.Lundqvist@gmail.com +# +# Displays Debian version +# + +echo "Debian version: $(cat /etc/debian_version)" diff --git a/FamDeb/etc/update-motd.d/11-aok-release b/FamDeb/etc/update-motd.d/11-aok-release deleted file mode 100755 index 092f9c84..00000000 --- a/FamDeb/etc/update-motd.d/11-aok-release +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# -# Part of https://github.com/jaclu/AOK-Filesystem-Tools -# -# License: MIT -# -# Copyright (c) 2023: Jacob.Lundqvist@gmail.com -# -# Displays AOK release info -# -f_aok_fs_release="/etc/aok-fs-release" - -# LF to create separaion from pam.d uname-a -echo - -if [ -e "$f_aok_fs_release" ]; then - echo "AOK-FS release: $(cat "$f_aok_fs_release")" -fi diff --git a/FamDeb/etc/update-motd.d/13-ish-release b/FamDeb/etc/update-motd.d/13-ish-release deleted file mode 100755 index 22f26483..00000000 --- a/FamDeb/etc/update-motd.d/13-ish-release +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -# -# Part of https://github.com/jaclu/AOK-Filesystem-Tools -# -# License: MIT -# -# Copyright (c) 2023: Jacob.Lundqvist@gmail.com -# -# Displays AOK release info -# -if [ -d /proc/ish ]; then - # Dont do this whilst chrooted in linux etc - echo "iSH release: $(cat /proc/ish/version)" -else - echo "iSH release: Can't be detected whilst chrooted" -fi -echo diff --git a/Debian/etc/update-motd.d/12-deb-vers b/FamDeb/etc/update-motd.d/24-set-color similarity index 57% rename from Debian/etc/update-motd.d/12-deb-vers rename to FamDeb/etc/update-motd.d/24-set-color index 1e003c06..2cc0c52c 100755 --- a/Debian/etc/update-motd.d/12-deb-vers +++ b/FamDeb/etc/update-motd.d/24-set-color @@ -9,8 +9,5 @@ # Displays AOK release info # -deb_version="/etc/debian_version" - -if [ -e "$deb_version" ]; then - echo "Debian release: $(cat "$deb_version")" -fi +echo +#printf "\e[35m" diff --git a/FamDeb/etc/update-motd.d/26-ish-release b/FamDeb/etc/update-motd.d/26-ish-release new file mode 100755 index 00000000..936befca --- /dev/null +++ b/FamDeb/etc/update-motd.d/26-ish-release @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Part of https://github.com/jaclu/AOK-Filesystem-Tools +# +# License: MIT +# +# Copyright (c) 2024: Jacob.Lundqvist@gmail.com +# +# Displays iSH version +# + +ish_version="$(cat /proc/ish/version 2>/dev/null)" +[ -z "$ish_version" ] && ish_version="Cant be detected whilst chrooted" +echo "iSH release: $ish_version" diff --git a/FamDeb/etc/update-motd.d/27-aok-release b/FamDeb/etc/update-motd.d/27-aok-release new file mode 100755 index 00000000..b073a46d --- /dev/null +++ b/FamDeb/etc/update-motd.d/27-aok-release @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Part of https://github.com/jaclu/AOK-Filesystem-Tools +# +# License: MIT +# +# Copyright (c) 2024: Jacob.Lundqvist@gmail.com +# +# Displays AOK release info +# + +aok_release="$(cat /etc/aok-fs-release 2>/dev/null)" +[ -z "$aok_release" ] && aok_release="Not found: /etc/aok-fs-release" +echo "AOK-FS release: $aok_release" diff --git a/FamDeb/etc/update-motd.d/28-clear-color b/FamDeb/etc/update-motd.d/28-clear-color new file mode 100755 index 00000000..06ab9925 --- /dev/null +++ b/FamDeb/etc/update-motd.d/28-clear-color @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Part of https://github.com/jaclu/AOK-Filesystem-Tools +# +# License: MIT +# +# Copyright (c) 2024: Jacob.Lundqvist@gmail.com +# +# Clear color for aok version info +# + +# printf "\e[0m" +echo diff --git a/TODO.md b/TODO.md index 6b21234c..f0ecfde0 100644 --- a/TODO.md +++ b/TODO.md @@ -173,52 +173,3 @@ since it is about to become more usefull, i should update it to ensure it is in line with the debian image when it comes to what is installed out of the door -## procps alpine 3.20 - -alpine 3.20 -procps issues - -bin/pidof --bin/pidwait -bin/ps --bin/slabtop - unable --bin/tload - unable --bin/vmstat - unable --bin/w - segfault -bin/watch -!sbin/sysctl -usr/bin/free -usr/bin/pgrep -usr/bin/pkill -usr/bin/pmap -usr/bin/pwdx -usr/bin/top -usr/bin/uptime - segfault - -=== bins when procps not installed: - -bin/pidwait - not found -bin/slabtop - not found -bin/tload - not found -bin/vmstat - not found -bin/w - not found -sbin/sysctl - fails - -=== older procps - -uptime -3.18 procps-ng-4.0.4-r0.apk -/usr/bin/uptime: -segfault - -3.17 procps-3.3.17-r3.apk -/usr/bin/uptime: -Error: /proc must be mounted [despite it being mounted] - -3.16 procps-3.3.17-r2.apk -/usr/bin/uptime: -Error: /proc must be mounted [despite it being mounted] - -3.14 procps-3.3.17-r0 -/usr/bin/uptime: -Error: /proc must be mounted [despite it being mounted] diff --git a/common_AOK/etc/skel/.common_rc b/common_AOK/etc/skel/.common_rc index fdafa726..4eda3108 100755 --- a/common_AOK/etc/skel/.common_rc +++ b/common_AOK/etc/skel/.common_rc @@ -35,10 +35,9 @@ set_current_shell_name() { # The SHELL variable only displays initial login shell # if you change shell, even using ` -l` to indicate # doing a login shell, it doesnt change. - # Instead I add CURRENT_SHELL to indicate what this shell is + # Instead I add CURRENT_SHELL to indicate what this shell is. + # On Alpine ash is usually softlinked to busybox # - - # Determine the current shell if [ -n "$FISH_VERSION" ]; then CURRENT_SHELL="fish" else @@ -46,6 +45,7 @@ set_current_shell_name() { case "$(basename "$(realpath /proc/$$/exe)")" in ash | busybox) CURRENT_SHELL="ash" ;; bash) CURRENT_SHELL="bash" ;; + dash) CURRENT_SHELL="dash" ;; zsh) CURRENT_SHELL="zsh" ;; *) CURRENT_SHELL="" ;; # unknown esac diff --git a/common_AOK/etc/skel/.profile b/common_AOK/etc/skel/.profile index 6c74f96c..02653781 100755 --- a/common_AOK/etc/skel/.profile +++ b/common_AOK/etc/skel/.profile @@ -12,32 +12,45 @@ # exists. # see /usr/share/doc/bash/examples/startup-files for examples. # the files are located in the bash-doc package. - +# # # Non-interactive shells wont read this by themselves. This ensures # that if they get here via idirect sourcing, they abort. # echo "$-" | grep -qv 'i' && return # non-interactive -# the default umask is set in /etc/profile; for setting the umask -# for ssh logins, install and configure the libpam-umask package. -#umask 022 - -case "$0" in - -"-ash" | "ash" | "/bin/ash" | "-dash" | "dash") +use_ash_env() { # # If ENV is defined ash & dash will use it + # on Alpine ash is usually softlinked to busybox # [ -f "$HOME/.ash_init" ] && export ENV="$HOME/.ash_init" - ;; +} + +# umask 022 + # # A bash login shell reads the first found of: # ~/.bash_profile ~/.bash_login ~/.profile # Since ~/.bash_profile is provided in AOK_FS # There will normally not be a need to handle bash here. # - -*) ;; - -esac +if [ -f /proc/$$/exe ]; then + case "$(basename "$(realpath /proc/$$/exe)")" in + ash | busybox | dash) + use_ash_env + ;; + *) ;; + esac +else + # /proc/$$/exe not found, fall back to $0 check + case "$0" in + "-ash" | "ash" | "/bin/ash" | "-dash" | "dash") + # + # If ENV is defined ash & dash will use it + # + use_ash_env + ;; + *) ;; + esac +fi diff --git a/common_AOK/etc/skel/.zshrc b/common_AOK/etc/skel/.zshrc index 898b129f..6b0b16f4 100755 --- a/common_AOK/etc/skel/.zshrc +++ b/common_AOK/etc/skel/.zshrc @@ -74,7 +74,7 @@ prompt_colors _user_host_name="%F{$PCOL_USERNAME}%n%F{$PCOL_GREY}@%F{$PCOL_HOSTNAME}$_hn" # -# Folder and success of last cmd on left +# CWD and success of last cmd on left # user@machine [sysload battery_lvl] time on right # PROMPT="%(?..%F{red}?%?)%F{$PCOL_CWD}%~%f%b%# " @@ -91,9 +91,14 @@ if true; then RPROMPT="$_s" unset _s else - RPROMPT="$_user_host_name $(get_sysload_lvl) %F{$PCOL_GREY}%*%f" + if [ -f /etc/alpine-release ]; then + RPROMPT="$_user_host_name $(get_sysload_lvl) %F{$PCOL_GREY}%*%f" + else + # iSH Debian doesn't provide sysload + RPROMPT="$_user_host_name %F{$PCOL_GREY}%*%f" + fi fi - + return 0 } precmd() { @@ -102,16 +107,6 @@ if true; then # initial prompt update update_prompt_content - - # - # update_prompt_content when called first time, ends up indicating - # exit code 1 even if called multiple times. - # This prompts displays exit code for previous command, so will therefore - # Imply there was an error. For now just doing a random action that - # succeeds solves the issue, so I just unset a random non-existing - # variable - # - unset foo_bar else RPROMPT="$_user_host_name %F{$PCOL_GREY}%*%f" fi diff --git a/common_AOK/setup_common_env.sh b/common_AOK/setup_common_env.sh index abbe2147..f273e7fb 100755 --- a/common_AOK/setup_common_env.sh +++ b/common_AOK/setup_common_env.sh @@ -199,9 +199,12 @@ setup_environment() { # If AOK_HOSTNAME_SUFFIX is defined and this runs on an aok kernel # on first boot aok -s on will be set # - aok -c off -H on -s off -C off - # only set if not chrooted - this_fs_is_chrooted || aok -l aok + aok -c off -H on -s off + # + # This will only take effect if system is not pre-built. + # Same settings will be done in setup_final_tasks.sh on dest platform + # + this_fs_is_chrooted || aok -l aok -C off setup_cron_env diff --git a/common_AOK/setup_final_tasks.sh b/common_AOK/setup_final_tasks.sh index 1bfa155e..917754d5 100755 --- a/common_AOK/setup_final_tasks.sh +++ b/common_AOK/setup_final_tasks.sh @@ -76,16 +76,16 @@ ensure_path_items_are_available() { aok_kernel_consideration() { msg_2 "aok_kernel_consideration()" - this_is_aok_kernel || { + if ! this_is_aok_kernel || this_fs_is_chrooted; then msg_3 "Not aok kernel!" - min_release 3.18 || { - msg_3 "procps wont work on regular iSH for Alpine < 3.18" - apk del procps || { - error_msg "apk del procps failed" - } - } + #min_release 3.18 || { + # msg_3 "procps wont work on regular iSH for Alpine < 3.18" + # apk del procps || { + # error_msg "apk del procps failed" + # } + #} return - } + fi [ -n "$AOK_APKS" ] && { msg_3 "Install packages only for AOK kernel" @@ -201,6 +201,7 @@ echo export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +# shellcheck source=/opt/AOK/tools/utils.sh [ -z "$d_aok_etc" ] && . /opt/AOK/tools/utils.sh . /opt/AOK/tools/ios_version.sh . /opt/AOK/tools/user_interactions.sh diff --git a/common_AOK/usr_local_bin/aok b/common_AOK/usr_local_bin/aok index 2da7d510..3538704e 100755 --- a/common_AOK/usr_local_bin/aok +++ b/common_AOK/usr_local_bin/aok @@ -68,11 +68,6 @@ $( echo "$txt" exit 0 } -# -c, --console Console method [launch|inittab] Now: $(console_mode_display) -# if autologin is desired, give extra param user_name -# launch - launched directly from iSH via 'Launch Cmd' -# inittab - launched via getty in inittab once bootup -# has completed. # shellcheck disable=SC2317 destfs_is_alpine() { @@ -212,9 +207,12 @@ continous_sessions_display() { launch_cmd_change() { lnch_cmd="$1" + [ -z "$lnch_cmd" ] && { error_msg "launch_cmd_change() - no param given, options are on/off" } + this_fs_is_chrooted && error_msg "Can't change launch-cmd on chrooted system" + case "$lnch_cmd" in "default") set_launch_cmd "$launch_cmd_default" @@ -333,9 +331,11 @@ aok_suffix_display() { console_mode_change() { use_console="$1" f_rc_conf=/etc/rc.conf + [ -z "$use_console" ] && { error_msg "console_mode_change() - no param given, options are on/off" } + this_fs_is_chrooted && error_msg "Can't change console on chrooted system" case "$use_console" in "on") @@ -436,13 +436,16 @@ console_mode_display() { #=============================================================== extralocking_change() { - this_is_aok_kernel || { - error_msg "extralocking_change() only usable on iSH-AOK kernels" - } do_elock="$1" + [ -z "$do_elock" ] && { error_msg "extralocking_change() - no param given, options are on/off" } + this_fs_is_chrooted && error_msg "Can't change extra_locking on chrooted system" + this_is_aok_kernel || { + error_msg "extralocking_change() only usable on iSH-AOK kernels" + } + case "$do_elock" in "on") echo "true" >"$f_elock" ;; "off") echo "false" >"$f_elock" ;; @@ -484,13 +487,16 @@ f_elock=/proc/ish/defaults/enable_extralocking #=============================================================== multicore_change() { - this_is_aok_kernel || { - error_msg "multicore_change() only usable on iSH-AOK kernels" - } do_multicore="$1" + [ -z "$do_multicore" ] && { error_msg "multicore_change() - no param given, options are on/off" } + this_fs_is_chrooted && error_msg "Can't change multicore on chrooted system" + this_is_aok_kernel || { + error_msg "multicore_change() only usable on iSH-AOK kernels" + } + case "$do_multicore" in "on") echo "true" >"$f_multicore" ;; "off") echo "false" >"$f_multicore" ;; @@ -548,7 +554,6 @@ while [ -n "$1" ]; do "-a" | "--autologin") # skip if $2 starts with - another option if [ -n "$2" ] && [ "${2%"${2#?}"}" != "-" ]; then - # this_fs_is_chrooted && error_msg "Can't change autologin on chrooted system" autologin_change "$2" shift # get rid of extra option else diff --git a/common_AOK/usr_local_bin/aok-versions b/common_AOK/usr_local_bin/aok-versions index 2a6b899d..b449c65a 100755 --- a/common_AOK/usr_local_bin/aok-versions +++ b/common_AOK/usr_local_bin/aok-versions @@ -13,22 +13,26 @@ # # Display versions of deployed environment # + +# printf "\e[35m" # set color - magenta + if test -f /etc/alpine-release; then - head -n 4 = 3.19 /usr/bin/uptime segfaults if procps is installed # This gives a warning # - #region warning - warn=" - -WARNING: If procps is installed on Alpine /usr/bin/uptime will segfault. - -This has been solved by soft-linking /usr/bin/uptime to /bin/busybox -So this warning is just informational, and wont be seen again until -procps is updated and potentially installs an incompatible uptime. -At that point this issue will be self corrected again. -" - #endregion # Only relevant for Alpine [ -f /etc/alpine-release ] || return + # if version check is not available, no check can be done + [ -f /opt/AOK/tools/vers_check.sh ] || { + echo "Unable to check Alpine version." + echo "If procps is installed on Alpine >= 3.19" + echo "/usr/bin/uptime will segfault." + return + } + + . /opt/AOK/tools/vers_check.sh + + # if older Alpine - all is good + ! min_version 3.19 && return + cmd_uptime=/usr/bin/uptime [ "$(realpath "$cmd_uptime")" = /bin/busybox ] && return rm -f "$cmd_uptime" ln -sf /bin/busybox "$cmd_uptime" - notification "$warn" + #region warning + notification " + +WARNING: If procps is installed on Alpine /usr/bin/uptime will segfault. + +This has been solved by soft-linking /usr/bin/uptime to /bin/busybox +So this warning is just informational, and wont be seen again until +procps is updated and potentially installs an incompatible uptime. +At that point this issue will be self corrected again. +" + #endregion } #=============================================================== @@ -97,5 +109,10 @@ else use_wall=false fi +[ ! -d /proc/ish ] && [ ! -f /etc/opt/AOK/this_fs_is_chrooted ] && { + notification "--- WARNING: $(basename "$0") - should only run on iSH" + exit 0 +} + coreutils_check uptime_check diff --git a/common_AOK/usr_local_bin/uptime b/common_AOK/usr_local_bin/uptime index 19d3ce6b..39af265d 100755 --- a/common_AOK/usr_local_bin/uptime +++ b/common_AOK/usr_local_bin/uptime @@ -9,57 +9,58 @@ # This serves two purposes: # # 1> If lines like: === System startup === -# can be found in /var/log/syslog, the corresponding timestamp -# will be assumed to be iSH boot time, (will be off by a few seconds) +# can be found in /var/log/syslog, the corresponding timestamp for +# the last match will be assumed to be iSH boot time, +# (this will be off by a few seconds from actual iSH startup). # Those lines are generated by the AOK inittab and aok_launcher. # If it is not found this fallbacks to iOS boot time via /proc/uptime # for Debian and for Alpine, the regular uptime is run instead showing # the same iOS boot time. # -# 2> In Debian on regular iSH, there is no /proc/loadavg -# This causes the regular uptime to fail. -# sysload is faked, always reporting 0.00 -# Be aware that the lack of /proc/loadavg also causes other tools -# such as top & htop to fail! +# 2> iSH doesnt currently provide /proc/loadavg +# Debians regular uptime fails badly - (because of no /proc/loadavg??) +# therefore sysload is faked, always reporting 0.00, 0.00, 0.00 +# On Alpine the BusyBox uptime can report sysload, so sysload is +# extracted via /usr/bin/uptime. # show_help() { - echo " + #region help text + cat < + -i, --ios display iOS instead of iSH uptime + -l, --load displays only sysload +For more details see uptime(1). +EOF + #endregion exit 0 } org_uptime() { - # Security check that it isnt linking to itself... $dbg && echo ">org_uptime()" >/dev/stderr - _p="$(realpath "$(dirname -- "$0")")" - f_this="$_p/$prog_name" cmd_org=/usr/bin/uptime - [ -e /usr/bin/uptime ] || { - cmd_busybox=/bin/busybox - if [ -e "$cmd_busybox" ]; then + [ ! -x "$cmd_org" ] && { + if [ -x /bin/busybox ]; then echo "Linking $cmd_org to busybox" - ln -sf "$cmd_busybox" "$cmd_org" + ln -sf /bin/busybox "$cmd_org" else echo "ERROR: original $cmd_org unavailable!" exit 1 fi - unset cmd_busybox } - [ "$(realpath "$cmd_org")" = "$f_this" ] && { + [ "$(realpath "$cmd_org")" = "$(realpath "$0")" ] && { echo "ERROR: $cmd_org points to this replacement uptime!" exit 1 } @@ -72,53 +73,38 @@ calculate_ish_uptime() { boot_time_epoch=$(date -d "$time_stamp_bootup" +%s) current_time=$(date +%s) uptime_seconds=$((current_time - boot_time_epoch)) - - unset boot_time_epoch current_time } calculate_ios_uptime() { - # Read the uptime from /proc/uptime $dbg && echo ">calculate_ios_uptime()" >/dev/stderr - uptime_raw="$(cut -d' ' -f1 /dev/null; then - raw_s_hundreds="$(echo "$uptime_raw" | cut -d. -f1)" - raw_s="$(echo "$uptime_raw" | cut -d. -f2)" - uptime_seconds="$(echo "$raw_s_hundreds * 100 + $raw_s" | bc)" + if [ -d /proc/ish ] && grep -qiv aok /proc/ish/version 2>/dev/null; then + raw_s_hundreds=$(echo "$uptime_raw" | cut -d. -f1) + raw_s=$(echo "$uptime_raw" | cut -d. -f2) + uptime_seconds=$(echo "$raw_s_hundreds * 100 + $raw_s" | bc) else - uptime_seconds="$uptime_raw" + uptime_seconds=$(echo "$uptime_raw" | awk '{print int($1)}') fi - - unset uptime_raw - unset raw_s_hundreds - unset raw_s } calculate_uptime() { + startup_notice="=== System startup ===" $dbg && echo ">calculate_uptime()" >/dev/stderr - time_stamp_bootup="$(grep "System startup" /var/log/syslog | - tail -n 1 | awk '{print $1" "$2}')" + time_stamp_bootup="$(grep "$startup_notice" /var/log/syslog | + tail -n 1 | + awk '{print $1" "$2}')" if [ -n "$time_stamp_bootup" ] && ! $force_ios_uptime; then calculate_ish_uptime - elif [ -f /etc/alpine-release ] && [ -z "$alpine_options" ]; then - # - # if org_uptime is a binary and not a soft link to busybox - # it would be able to handle options, but instead of detecting - # that its simpler to use calculate_ios_uptime - # - org_uptime # use the normal uptime - exit 0 else calculate_ios_uptime fi $dbg && echo ">calculate_uptime() - doing the calculations" >/dev/stderr - # Calculate days, hours, minutes, and seconds - ut_weeks=$(echo "$uptime_seconds / 86400 / 7" | bc) - ut_days=$(echo "$uptime_seconds / 86400" | bc) - ut_hours=$(echo "($uptime_seconds % 86400) / 3600" | bc) - ut_minutes=$(echo "($uptime_seconds % 3600) / 60" | bc) - # ut_seconds=$(echo "$uptime_seconds % 60" | bc) + # Calculate days, hours, minutes + ut_days=$((uptime_seconds / 86400)) + ut_hours=$(((uptime_seconds % 86400) / 3600)) + ut_minutes=$(((uptime_seconds % 3600) / 60)) } display_sysload() { @@ -132,56 +118,43 @@ display_sysload() { } show_pretty() { + $dbg && echo ">show_pretty()" >/dev/stderr output="$ut_minutes minutes" [ "$ut_hours" -gt 0 ] && output="$ut_hours hours, $output" [ "$ut_days" -gt 0 ] && output="$ut_days days, $output" - [ "$ut_weeks" -gt 0 ] && output="$ut_weeks weeks, $output" - echo "up $output" } show_since() { - date -d "$uptime_seconds seconds ago" "+%Y-%m-%d %H:%M:%S" + $dbg && echo ">show_since($uptime_seconds)" >/dev/stderr + if [ -f /etc/alpine-release ]; then + current_timestamp=$(date +%s) + new_timestamp=$((current_timestamp - uptime_seconds)) + date -u -d "@$new_timestamp" "+%Y-%m-%d %H:%M:%S" + else + date -d "$uptime_seconds seconds ago" "+%Y-%m-%d %H:%M:%S" + fi } show_version() { + $dbg && echo ">show_version()" >/dev/stderr _f=/etc/aok-fs-release - if [ -f "$_f" ]; then - aok_vers="$(cat "$_f")" - else - aok_vers="unknown AOK-FS version" - fi + aok_vers=$(cat "$_f" 2>/dev/null || echo "unknown AOK-FS version") echo "uptime from AOK-FS $aok_vers" - - unset aok_vers + exit 0 } default_view() { - # Print the uptime in the format used by uptime command $dbg && echo ">default_view()" >/dev/stderr - # < 1h - # 17:42:51 up 27 min, 1 user, - - $dbg && echo ">default_view() - minutes" >/dev/stderr - if [ "$ut_minutes" -lt 10 ]; then - _minutes=$(printf "0%d" "$ut_minutes") - else - _minutes=$(printf "%d" "$ut_minutes") - fi - $dbg && echo ">default_view() - hours" >/dev/stderr - if [ "$ut_hours" -lt 10 ]; then - _hours=$(printf " %d" "$ut_hours") - else - _hours=$(printf "%d" "$ut_hours") - fi + _minutes=$(printf "%02d" "$ut_minutes") + _hours=$(printf "%d" "$ut_hours") output="$ut_minutes min" [ "$ut_hours" -gt 0 ] && output="$_hours:$_minutes" [ "$ut_days" -gt 0 ] && output="$ut_days days, $output" - [ "$ut_weeks" -gt 0 ] && output="$ut_weeks weeks, $output" - user_count="$(find /dev/pts/* | wc -l)" + user_count=$(find /dev/pts/* | wc -l) user_field="$user_count user" [ "$user_count" -gt 1 ] && user_field="${user_field}s" @@ -199,25 +172,16 @@ default_view() { force_ios_uptime=false display_mode="default" -# if Alpine uptime is used this provides the desired options -alpine_options="" dbg=false -prog_name="$(basename "$0")" - while [ -n "$1" ]; do case "$1" in -h | --help) show_help ;; -d) dbg=true ;; -i | --ios) force_ios_uptime=true ;; - -p | --pretty) - display_mode="pretty" - alpine_options="$alpine_options -p" - ;; - -s | --since) - display_mode="since" - alpine_options="$alpine_options -s" - ;; + -l | --load) display_mode="load" ;; + -p | --pretty) display_mode="pretty" ;; + -s | --since) display_mode="since" ;; -V | --version) show_version ;; *) echo "uptime: invalid option -- '$1'" @@ -233,6 +197,7 @@ case "$display_mode" in default) default_view ;; pretty) show_pretty ;; since) show_since ;; +load) display_sysload ;; *) echo "Invalid display_mode [$display_mode]" ;; diff --git a/common_AOK/usr_local_bin/wall b/common_AOK/usr_local_bin/wall index 861d00a8..320cc8d8 100755 --- a/common_AOK/usr_local_bin/wall +++ b/common_AOK/usr_local_bin/wall @@ -109,22 +109,6 @@ while [ -n "$1" ]; do shift done -[ -c /dev/console ] && { - # if pts/0 is only console, display msg this way - pgrep -t pts/0 >/dev/null || display_msg >/dev/console -} - -# get pts in fashion suitable for pgrep -cd /dev || { - msg="ERROR: $0 - failed to cd /dev" - echo "$msg" - /usr/local/bin/logger "$0" "$msg" - exit 1 -} - -for pts in pts/*; do - pgrep -t "$pts" >/dev/null || continue # skip if not used - - pts=/dev/"$pts" # back to normal notation +for pts in /dev/pts/*; do display_msg >"$pts" done diff --git a/common_AOK/usr_local_sbin/aok_launcher b/common_AOK/usr_local_sbin/aok_launcher index b267925c..28b8dc75 100755 --- a/common_AOK/usr_local_sbin/aok_launcher +++ b/common_AOK/usr_local_sbin/aok_launcher @@ -22,40 +22,11 @@ # directly to set up the user session # -error_msg() { - echo - echo "ERROR[$0]: $1" - echo - log_it "$1" -} - -log_it() { - # In recovery-mode, skip logging to minimize risk of issues - [ -f "$f_recovery_mode" ] && return - - # if no supported loggers are found, fall back to a non-dependency solution - if [ -x "$cmd_logger" ]; then - "$cmd_logger" "$prog_name" "$*" - else - echo "$(date +"%Y-%m-%d %H:%M:%S") ${prog_name}: $*" >>/var/log/messages - fi -} - -print_log() { - # - # In case of bootup issues, this output is both displayed - # and logged to a file, so that it can be reviewed - # This is not used for all output, only "essentials" indicating - # statuses during startup - # For log only items, give noecho as 2nd param - # - [ "$2" != "noecho" ] && echo "$1" - # - # Since other tools launched by this might have changed it, set it - # here for now, later check if it is needed - # - log_it "$1" -} +#--------------------------------------------------------------- +# +# Device checks +# +#--------------------------------------------------------------- fix_stdio_device() { fsd_src="$1" @@ -159,149 +130,204 @@ verify_devs() { verify_device /dev/zero 1 5 } -update_deb_log_kill_cmd() { - # - # Since the cmd_tail might change, always - # update the kill cmd to its current definition - # - cmd_kill_tail_logging=/usr/local/sbin/kill_tail_logging - #region kill_tail_logging cmd - echo "#!/bin/sh -# Called from /usr/local/bin/console-restart -# Replaced by /usr/local/sbin/aok_launcher during each reboot +#--------------------------------------------------------------- +# +# Recovery mode +# +#--------------------------------------------------------------- -( - echo - echo 'Console tailing of /var/log/* will be restarted' - echo 'Non text-files will be ignored' -) >/dev/console +recovery_mode_enable() { + # Save current stty settings + org_stty=$(stty -g) -pgrep -f \"$cmd_tail\" | xargs -r kill -" >"$cmd_kill_tail_logging" - #endregion - chown root: "$cmd_kill_tail_logging" - chmod 744 "$cmd_kill_tail_logging" + # Configure terminal to read a single character without waiting for Enter + stty -icanon -echo min 0 time 0 - unset cmd_kill_tail_logging + recovery_mode_active=true + # echo "sleeping 1" + # sleep 1 + recovery_mode_probe initial # initial check } -check_for_recovery_mode() { - $recovery_mode_canceled && return +recovery_mode_disable() { + $recovery_mode_active || return + recovery_mode_probe final # one last check + recovery_mode_active=false + if [ -n "$org_stty" ]; then + stty "$org_stty" + unset org_stty + [ "$1" != "silent" ] && { + echo "recovery-mode no longer possible" + echo + } + else + echo "NOTICE: Variable org_stty already cleared!" + fi +} - # Disable terminal line buffering and enable read without Enter - stty -icanon min 0 time 0 +recovery_mode_probe() { + $recovery_mode_active || return + key=$(dd bs=1 count=1 2>/dev/null) + case "$key" in + r | R) + recovery_mode_trigger "$1" + ;; + *) ;; + esac +} - # Read a single character - keypress=$(dd bs=1 count=1 2>/dev/null) +recovery_mode_trigger() { + # First do urgent tasks that are somewhat time sensitive + touch "$f_recovery_mode" - # Revert terminal settings - stty icanon + $recovery_mode_active || { + error_msg "recovery_mode_trigger($1) - called when recovery is not active" + return + } + echo "><> recovery_mode_trigger($1)" + f_recovery_mode_log=/var/log/recovery-mode.log + recovery_mode_disable silent + trap '' INT # abort capturing Ctrl-C - # Check if a key was pressed - case "$keypress" in - "r" | "R") - # First do urgent tasks that are somewhat time sensitive - touch "$f_recovery_mode" - trap '' INT # abort capturing Ctrl-C + # in case recovey was triggered before this was called + verify_devs - f_recovery_mode_log=/var/log/recovery-mode.log + #region recovery explaination + cat </dev/null)" || - aok_vers="*** Failed to read $f_aok_release ***" - else - aok_vers=Unknown - fi +#--------------------------------------------------------------- +# +# Console mode - using /dev/pts/0 as console only +# +#--------------------------------------------------------------- - if test -f "$f_rel_alpine"; then - fs_name="Alpine $(cat "$f_rel_alpine" 2>/dev/null)" || - fs_name="Alpine Unknown" - elif test -f "$f_rel_devuan"; then - # - # Devuan must come before Debian, since it also has the - # f_rel_debian file - # - fs_name="Devuan $(cat "$f_rel_devuan" 2>/dev/null)" || - fs_name="Devuan Unknown" - elif test -f "$f_rel_debian"; then - fs_name="Debian $(cat "$f_rel_debian" 2>/dev/null)" || - fs_name="Debian Unknown" - else - fs_name=Unknown - fi +update_deb_log_kill_cmd() { + # + # Since the cmd_tail might change, always + # update the kill cmd to its current definition + # + cmd_kill_tail_logging=/usr/local/sbin/kill_tail_logging + #region kill_tail_logging cmd + echo "#!/bin/sh +# Called from /usr/local/bin/console-restart +# Replaced by /usr/local/sbin/aok_launcher during each reboot +( echo - echo "aok_launcher - AOK: $aok_vers - Filesystem: $fs_name" - header_msg="" - [ -f "$f_pts_0_as_console" ] && { - header_msg="/dev/pts/0 is used as /dev/console" - if $this_is_pts0; then - header_msg="$header_msg - no session will be started on this vterm" - else - header_msg="$header_msg - this is: $(tty)" - fi - echo "$header_msg" - } - if $this_is_pts0 || [ -f "$f_this_is_chrooted" ]; then - echo "Press 'r' during bootup for recovery-mode" - echo - fi + echo 'Console tailing of /var/log/* will be restarted' + echo 'Non text-files will be ignored' +) >/dev/console - unset aok_vers fs_name header_msg +pgrep -f \"$cmd_tail\" | xargs -r kill +" >"$cmd_kill_tail_logging" + #endregion + chown root: "$cmd_kill_tail_logging" + chmod 744 "$cmd_kill_tail_logging" + + unset cmd_kill_tail_logging } kill_console_tail() { @@ -389,158 +415,193 @@ monitor_log_files() { exit 1 # shouldnt get here, but just in case } -bootup() { - # at bootup also log it - - /usr/local/bin/network-check.sh - - if [ -f "$f_pts_0_as_console" ]; then - # also done in profile for interactive vterms - /usr/local/bin/check-env-compatible - - check_for_recovery_mode - [ "$(stat -c "%t %T" /dev/console)" != "88 0" ] && { - echo "Setting up /dev/pts/0 as console" - rm -f /dev/console && mknod -m 222 /dev/console c 136 0 - } - - indicate_end_of_recovery_window +#--------------------------------------------------------------- +# +# bootup +# +#--------------------------------------------------------------- - if [ -x "$cmd_custom_console_monitor" ]; then - handle_custom_console_monitor - else - monitor_log_files - fi +display_header() { + if [ -f "$f_aok_release" ]; then + aok_vers="$(cat "$f_aok_release" 2>/dev/null)" || + aok_vers="*** Failed to read $f_aok_release ***" else - [ "$(stat -c "%t %T" /dev/console)" != "5 1" ] && { - echo "Reverting console to normal mode" - rm -f /dev/console && mknod -m 666 /dev/console c 5 1 - } - indicate_end_of_recovery_window + aok_vers=Unknown fi - if [ ! -f "$f_this_is_chrooted" ]; then - runlevel_wait + if test -f "$f_rel_alpine"; then + fs_name="Alpine $(cat "$f_rel_alpine" 2>/dev/null)" || + fs_name="Alpine Unknown" + elif test -f "$f_rel_devuan"; then + # + # Devuan must come before Debian, since it also has the + # f_rel_debian file + # + fs_name="Devuan $(cat "$f_rel_devuan" 2>/dev/null)" || + fs_name="Devuan Unknown" + elif test -f "$f_rel_debian"; then + fs_name="Debian $(cat "$f_rel_debian" 2>/dev/null)" || + fs_name="Debian Unknown" else - echo - echo "This is chrooted, so runlevel_wait & network check are skipped" - echo + fs_name=Unknown fi -} -set_deploy_aok_abort() { - trap '' INT # abort capturing Ctrl-C echo - print_log "*** Aborting deploy, dropping to shell ***" - echo - /bin/bash - exit 1 + echo "aok_launcher - AOK: $aok_vers - Filesystem: $fs_name" + header_msg="" + [ -f "$f_pts_0_as_console" ] && { + header_msg="/dev/pts/0 is used as /dev/console" + if $this_is_pts0; then + header_msg="$header_msg - no session will be started on this vterm" + else + header_msg="$header_msg - this is: $(tty)" + fi + echo "$header_msg" + } + if $this_is_pts0 || [ -f "$f_this_is_chrooted" ]; then + echo "Press 'r' during bootup for recovery-mode" + echo + fi + + unset aok_vers fs_name header_msg } -deploy_aok() { - # - # During deploy triggered by aok, you can hit Ctrl-C to get a shell - # if you need to inspect something - # - trap 'set_deploy_aok_abort INT' INT - # - # This is a new AOK-FS that has not yet completed its setup - # continue the deploy - # - indicate_end_of_recovery_window - echo - echo "******************************************************" - echo "* *" - echo "* AOK-FS deploy has not completed, continuing it *" - echo "* *" - echo "* Deploy can be aborted by pressing Ctrl-C *" - echo "* *" - echo "******************************************************" - echo +bootup() { + # at bootup also log it + /usr/local/bin/network-check.sh - da_depl_step="$(cat "$f_deploy_state")" - /usr/local/bin/logger aok_launcher Triggering deploy step: "$da_depl_step" - # AOK-FS uses /etc/profile as placeholder for deploy steps - if /etc/profile; then - /usr/local/bin/logger aok_launcher Deploy completed - "$da_depl_step" + if [ -f "$f_pts_0_as_console" ]; then + # also done in profile for interactive vterms + /usr/local/bin/check-env-compatible + + recovery_mode_probe bootup + [ "$(stat -c "%t %T" /dev/console)" != "88 0" ] && { + echo "Setting up /dev/pts/0 as console" + rm -f /dev/console && mknod -m 222 /dev/console c 136 0 + } + + recovery_mode_disable + + if [ -x "$cmd_custom_console_monitor" ]; then + handle_custom_console_monitor + else + monitor_log_files + fi else - error_msg "returned from the deploy procedure!" - echo "Since the File System probably is not fully deployed," - echo "it is impposisble to say if it is meaningfull to continue" - echo "You have been warned..." - echo - sleep 3 - set_deploy_aok_abort + [ "$(stat -c "%t %T" /dev/console)" != "5 1" ] && { + echo "Reverting console to normal mode" + rm -f /dev/console && mknod -m 666 /dev/console c 5 1 + } fi - unset da_depl_step - trap '' INT # abort capturing Ctrl-C + recovery_mode_disable - if [ -f "$f_deploy_state" ]; then - echo - echo "A new deploy state has been reached: $(cat "$f_deploy_state")" + if [ ! -f "$f_this_is_chrooted" ]; then + runlevel_wait + else echo - echo "It is recomended to reboot at this point" - echo "to let the next step be processed." + echo "This is chrooted, so runlevel_wait & network check are skipped" echo - set_deploy_aok_abort fi - - echo - echo "******************************************************" - echo "* *" - echo "* Returned from deploy, resuming this Launch cmd *" - echo "* *" - echo "* A reboot is recomended, to ensure all services *" - echo "* are running. *" - echo "* *" - echo "******************************************************" - echo - # Ensure nothing that shouldnt be there was installed - /usr/local/bin/check-env-compatible - sleep 3 -} - -set_abort_runlevel_wait() { - echo - _s="*** Ctrl-C captured - aborting wait for runlevel" - _s="$_s $expected_runlevel ***" - print_log "$_s" - unset _s - echo - abort_runlevel_wait=1 } runlevel_wait() { trap 'set_abort_runlevel_wait' INT while true; do - check_for_recovery_mode + recovery_mode_probe runlevel-wait current_runlevel="$(rc-status -r)" if [ "$current_runlevel" = "$expected_runlevel" ]; then - echo "runlevel is now '$expected_runlevel'" + #echo "runlevel is now: '$expected_runlevel'" + + # clear before exiting loop + unset current_runlevel + break fi _s="current runlevel is $current_runlevel - waiting for" _s="$_s $expected_runlevel - press Ctrl-C to abort wait" - sleep 2 + + # clear before potential exit unset current_runlevel _s + + sleep 2 [ -f "$f_recovery_mode" ] && return [ "$abort_runlevel_wait" = "1" ] && break done trap '' INT # abort capturing Ctrl-C - print_log "runlevel_wait completed, runlevel is now $(rc-status -r)" noecho + print_log "runlevel_wait completed, runlevel is now: $(rc-status -r)" } -handle_etc_issue() { - # - # I havent managed to get /etc/issue to display on console sessions. - # so manual handling - # - if [ -f "$f_issue_file" ] && [ -f "$f_profile_hints" ]; then - echo - cat "$f_issue_file" - fi +set_abort_runlevel_wait() { + trap '' INT # abort capturing Ctrl-C + echo + _s="*** Ctrl-C captured - aborting wait for runlevel" + _s="$_s $expected_runlevel ***" + print_log "$_s" + unset _s + echo + abort_runlevel_wait=1 +} + +#--------------------------------------------------------------- +# +# vterm logins +# +#--------------------------------------------------------------- + +handle_logins() { + while true; do + # + # Ensure params are tried for each login attempt, in case they + # have been changed during the current session, and continous + # logins is set + # + ignore_login_params=0 + login_with_param_check + [ "$login_ex_code" != "0" ] && { + error_msg "$f_login_prog exited with#3: $login_ex_code" + } + + if [ -f "$f_this_is_chrooted" ]; then + _s="This is chrooted, always terminating on logout," + _s="$_s this should also exit the chroot" + print_log "$_s" + exit 0 + fi + + if [ -f "$f_logins_continous" ]; then + echo + _s="Will spawn a new login session. If this is not requested," + _s="$_s run aok" + print_log "$_s" + unset _s + echo + sleep 1 + else + # echo + # echo "To enable continous vterm sessions, run aok" + if $this_is_pts0; then + # echo + # echo "Shutting down system..." + # echo + /usr/local/sbin/shutdown now + sleep 30 # give shutdown plenty of time to complete + exit # this will insta-kill iSH + else + print_log "Terminating vterm $(tty)" + sleep 2 + exit + fi + fi + done + + _s="=== Fell out of infinite aok_launcher login loop -" + _s="$_s Should really not happen!" + print_log "$_s" + unset _s + echo "will sleep forever, please shutdown iSH" + /bin/sleep infinity } login_with_param_check() { @@ -604,58 +665,56 @@ login_with_param_check() { fi } -handle_logins() { - while true; do - # - # Ensure params are tried for each login attempt, in case they - # have been changed during the current session, and continous - # logins is set - # - ignore_login_params=0 - login_with_param_check - [ "$login_ex_code" != "0" ] && { - error_msg "$f_login_prog exited with#3: $login_ex_code" - } +handle_etc_issue() { + # + # I havent managed to get /etc/issue to display on console sessions. + # so manual handling + # + if [ -f "$f_issue_file" ] && [ -f "$f_profile_hints" ]; then + echo + cat "$f_issue_file" + fi +} - if [ -f "$f_this_is_chrooted" ]; then - _s="This is chrooted, always terminating on logout," - _s="$_s this should also exit the chroot" - print_log "$_s" - exit 0 - fi +#--------------------------------------------------------------- +# +# Various +# +#--------------------------------------------------------------- - if [ -f "$f_logins_continous" ]; then - echo - _s="Will spawn a new login session. If this is not requested," - _s="$_s run aok" - print_log "$_s" - unset _s - echo - sleep 1 - else - # echo - # echo "To enable continous vterm sessions, run aok" - if $this_is_pts0; then - # echo - # echo "Shutting down system..." - # echo - /usr/local/sbin/shutdown now - sleep 30 # give shutdown plenty of time to complete - exit # this will insta-kill iSH - else - print_log "Terminating vterm $(tty)" - sleep 2 - exit - fi - fi - done +error_msg() { + echo + echo "ERROR[$0]: $1" + echo + log_it "$1" +} - _s="=== Fell out of infinite aok_launcher login loop -" - _s="$_s Should really not happen!" - print_log "$_s" - unset _s - echo "will sleep forever, please shutdown iSH" - /bin/sleep infinity +log_it() { + # In recovery-mode, skip logging to minimize risk of issues + [ -f "$f_recovery_mode" ] && return + + # if no supported loggers are found, fall back to a non-dependency solution + if [ -x "$cmd_logger" ]; then + "$cmd_logger" "$prog_name" "$*" + else + echo "$(date +"%Y-%m-%d %H:%M:%S") ${prog_name}: $*" >>/var/log/syslog + fi +} + +print_log() { + # + # In case of bootup issues, this output is both displayed + # and logged to a file, so that it can be reviewed + # This is not used for all output, only "essentials" indicating + # statuses during startup + # For log only items, give noecho as 2nd param + # + [ "$2" != "noecho" ] && echo "$1" + # + # Since other tools launched by this might have changed it, set it + # here for now, later check if it is needed + # + log_it "$1" } #=============================================================== @@ -664,57 +723,76 @@ handle_logins() { # #=============================================================== +# +# Just set the bare min variables needed for recovery mode, in order +# to hopefully capture inittab before it takes any action +# +# state_prefix=/etc/opt/AOK +# f_recovery_mode="$state_prefix"/recovery-mode +# f_pts_0_as_console="$state_prefix"/pts_0_as_console +# cmd_logger=/usr/local/bin/logger +# rm -f "$f_recovery_mode" +# recovery_mode_enable + +# Continue with variable definitions state_prefix=/etc/opt/AOK -recovery_mode_canceled=false -f_pts_0_as_console="$state_prefix"/pts_0_as_console -f_recovery_mode="$state_prefix"/recovery-mode f_inittab_can_start="$state_prefix"/inittab_can_start - -# Ensure no left-overs from a previous boot -rm -f "$f_inittab_can_start" -rm -f "$f_recovery_mode" - -check_for_recovery_mode - -prog_name=$(basename "$0") -expected_runlevel="default" -# f_status_log="/var/log/aok_launcher.log" -f_issue_file="/etc/issue" -f_login_prog="/bin/login" - f_deploy_state="$state_prefix"/deploy_state f_logins_continous="$state_prefix"/login-continous f_login_default_user="$state_prefix"/login-default-username f_profile_hints="$state_prefix"/show_profile_hints +f_pts_0_as_console="$state_prefix"/pts_0_as_console +f_recovery_mode="$state_prefix"/recovery-mode f_this_is_chrooted="$state_prefix"/this_fs_is_chrooted + f_aok_release=/etc/aok-fs-release f_rel_alpine=/etc/alpine-release f_rel_devuan=/etc/devuan_version f_rel_debian=/etc/debian_version -cmd_logger=/usr/local/bin/logger +f_issue_file="/etc/issue" +f_login_prog="/bin/login" + +# f_status_log="/var/log/aok_launcher.log" + +expected_runlevel="default" +recovery_mode_active=false + cmd_custom_console_monitor=/usr/local/sbin/custom_console_monitor cmd_tail="tail -n 0 -f " +cmd_logger=/usr/local/bin/logger if [ "$(tty)" = "/dev/pts/0" ]; then this_is_pts0=true else this_is_pts0=false fi -check_for_recovery_mode -if $this_is_pts0 || [ -f "$f_this_is_chrooted" ]; then +# Ensure no left-overs from a previous boot +rm -f "$f_inittab_can_start" +rm -f "$f_recovery_mode" +rm -f "$f_recovery_mode_log" + +prog_name=$(basename "$0") + +recovery_mode_enable + +[ -f "$f_this_is_chrooted" ] && { + # When chrooted, initttab wont exexute so do such tasks here + print_log "----- chrooted init tasks -----" noecho /usr/local/bin/logger "$prog_name" "=== System startup ===" - _s="$prog_name - iSH Booted at: $(date '+%Y-%m-%d')" - _s="${_s}$(/usr/local/bin/uptime)" - echo "$_s" - unset _s -fi + /usr/local/sbin/reset-run-dir + /usr/local/sbin/rotate-logs.sh + [ -f "$f_rel_alpine" ] && { + /usr/local/sbin/update-motd + } +} -verify_devs [ -f "$f_rel_debian" ] && update_deb_log_kill_cmd -check_for_recovery_mode display_header +recovery_mode_probe main1 +verify_devs +recovery_mode_probe main2 # If deploy has not completed - handle it [ -f "$f_deploy_state" ] && deploy_aok @@ -725,5 +803,5 @@ else /usr/local/bin/network-check.sh fi -[ -f "$f_this_is_chrooted" ] && indicate_end_of_recovery_window +recovery_mode_disable main3 handle_logins diff --git a/common_AOK/usr_local_sbin/halt b/common_AOK/usr_local_sbin/halt index 925f17ae..5800c16d 100755 --- a/common_AOK/usr_local_sbin/halt +++ b/common_AOK/usr_local_sbin/halt @@ -35,6 +35,18 @@ prog_name=$(basename "$0") exit 1 } +# remove some stat files + +state_prefix=/etc/opt/AOK +f_inittab_can_start="$state_prefix"/inittab_can_start + +[ -f "$f_inittab_can_start" ] && { + /usr/local/bin/logger "$prog_name" "WARNING found: $f_inittab_can_start" +} +rm -f "$f_inittab_can_start" +rm -f "$state_prefix"/recovery-mode +rm -f /var/log/recovery-mode.log + # # sync & sleep probably not needed on iSH, but its supposed to be # done now :) @@ -51,15 +63,25 @@ sleep 1 key_pids="$(pgrep -f aok_launcher)" [ -n "$key_pids" ] && do_shutdown aok_launcher -# a session on console -key_pids="$(pgrep -t pts/0)" +if [ -f /etc/alpine-release ]; then + # + # Alpine busybox pgrep does not have -t option + # workarround is to scan for pts/0 procs via ps -o pid,tty + # + pts0_id="$(stat -c "%t %T\n" /dev/pts/0 | + awk '{ printf("%d,%d\n", strtonum("0x"$1), strtonum("0x"$2)) }')" + # shellcheck disable=SC2009 # we need to do ps grep in this case + key_pids="$(ps -o pid,tty | grep "$pts0_id" | awk '{print $1}')" +else + key_pids="$(pgrep -t pts/0)" +fi [ -n "$key_pids" ] && do_shutdown pts/0 # login sessions key_pids="$(pgrep -f "login -f")" [ -n "$key_pids" ] && do_shutdown "'login -f'" -# find init pid +# find init pid - usually but not absolutely allways 1... key_pids="$(pgrep -f "init ")" [ -n "$key_pids" ] && do_shutdown "init via pgrep" diff --git a/common_AOK/usr_local_sbin/rotate-logs.sh b/common_AOK/usr_local_sbin/rotate-logs.sh index fa5b4a7d..7759090e 100755 --- a/common_AOK/usr_local_sbin/rotate-logs.sh +++ b/common_AOK/usr_local_sbin/rotate-logs.sh @@ -48,7 +48,7 @@ for log_file in "$d_log"/*; do [ "$(basename "$log_file")" = "lastlog" ] && continue # special file [ -f "$log_file" ] || continue # not a file - file_size="$(stat --printf='%s' "$log_file")" + file_size="$(stat -c '%s' "$log_file")" [ -f "$log_file" ] && [ "$file_size" -gt "$max_size" ] && { # > 20k # Set the rotated file name _fn="$(dirname "$log_file")/$(date +"%y%m%d-%H%M%S")" diff --git a/tools/aok_fs-common b/tools/aok_fs-common new file mode 100644 index 00000000..73d11556 --- /dev/null +++ b/tools/aok_fs-common @@ -0,0 +1,39 @@ +#!/bin/sh +# This is sourced. Fake bang-path to help editors and linters +# +# Part of https://github.com/jaclu/AOK-Filesystem-Tools +# +# License: MIT +# +# Copyright (c) 2023-2024: Jacob.Lundqvist@gmail.com +# +# Common environment for aok_fs-save & aok_fs-replace +# + +d_aok_fs="$TMPDIR"/aok_fs + +d_aok_saves="$TMPDIR"/saved_fs + +mkdir -p "$d_aok_saves" || { + error_msg "Failed to create: $d_aok_saves" +} + +[ ! -d "$d_aok_fs" ] && { + error_msg "d_aok_fs is not a dir: $d_aok_fs" +} + +[ ! -d "$d_aok_saves" ] && { + error_msg "d_aok_saves is not a dir: $d_aok_saves" +} + +if hostfs_is_alpine; then + chs_procs="$(lsof 2>/dev/null | grep "$d_aok_fs" | + awk '{print $1 }' | sort | uniq | tr '\n' ' ')" +else + chs_procs="$(lsof 2>/dev/null | grep "$d_aok_fs" | + awk '{print $2 }' | sort | uniq | tr '\n' ' ')" +fi +[ -n "$chs_procs" ] && { + error_msg "it seems a chroot is active pids: $chs_procs" +} +unset chs_procs diff --git a/tools/aok_fs-replace b/tools/aok_fs-replace new file mode 100755 index 00000000..32a85771 --- /dev/null +++ b/tools/aok_fs-replace @@ -0,0 +1,51 @@ +#!/bin/sh +# +# Part of https://github.com/jaclu/AOK-Filesystem-Tools +# +# License: MIT +# +# Copyright (c) 2024: Jacob.Lundqvist@gmail.com +# +# Replace the current aok_fs +# + +hide_run_as_root=1 . /opt/AOK/tools/run_as_root.sh +[ -z "$d_aok_etc" ] && . /opt/AOK/tools/utils.sh + + +. /opt/AOK/tools/aok_fs-common || { + error_msg "Failed to source aok_fs-common" +} + +if [ "$(basename "$1")" = "$1" ]; then + replacement_fs="$d_aok_saves/$1" +else + replacement_fs="$(realpath "$1")" +fi + +[ ! -f "$replacement_fs" ] && { + error_msg "Couldt find $replacement_fs" +} + +msg_1 "Will use: $(basename "$replacement_fs")" +msg_2 "Clearing current FS: $d_aok_fs" +rm -rf "$d_aok_fs" || { + error_msg "Failed to clear $d_aok_fs" +} + +mkdir "$d_aok_fs" + +cd "$d_aok_fs" || { + error_msg "Failed to cd into $d_aok_fs" +} + +[ "$(pwd)" != "$d_aok_fs" ] && { + error_msg "pwd is not $d_aok_fs" +} + +msg_2 "Untaring: $replacement_fs" +tar xfz "$replacement_fs" || { + echo + error_msg "Failed to untar $replacement_fs" +} +msg_3 "Done!" diff --git a/tools/aok_fs-save b/tools/aok_fs-save new file mode 100755 index 00000000..47d0ad51 --- /dev/null +++ b/tools/aok_fs-save @@ -0,0 +1,64 @@ +#!/bin/sh +# +# Part of https://github.com/jaclu/AOK-Filesystem-Tools +# +# License: MIT +# +# Copyright (c) 2024: Jacob.Lundqvist@gmail.com +# +# Save current aok_fs into saved_fs, tar file name will be +# auto generated based on current FS +# + +hide_run_as_root=1 . /opt/AOK/tools/run_as_root.sh +[ -z "$d_aok_etc" ] && . /opt/AOK/tools/utils.sh + +. /opt/AOK/tools/aok_fs-common || { + error_msg "Failed to source common-aok-fs-tar" +} + +f_alpine_release="$d_aok_fs"/etc/alpine-release +f_debian_version="$d_aok_fs"/etc/debian_version + +if [ -f "$f_alpine_release" ]; then + # seems to be Aline + tar_name="Alpine-$(cat "$f_alpine_release")" + time_estimate="30s" +elif [ -f "$f_debian_version" ]; then + tar_name="Debian-$(cat "$f_debian_version")" + time_estimate="63s" +else + error_msg "failed to detect Alpine/Debian" +fi + +aok_vers="$(cat "$d_aok_fs"/etc/aok-fs-release)" || { + error_msg "failed to detect aok-fs release" +} +tar_name="$d_aok_saves/$tar_name-AOK-$aok_vers-done.tgz" + +cd "$d_aok_fs" || { + error_msg "Failed to cd into $d_aok_fs" +} + +[ "$(pwd)" != "$d_aok_fs" ] && { + error_msg "pwd is not $d_aok_fs" +} + +msg_1 "Will crate: $(basename "$tar_name")" + +f_tar_tmp="$d_aok_saves"/tmp.tgz +msg_2 "Creating $f_tar_tmp (aprox $time_estimate)" +tar cfz "$f_tar_tmp" . || { + echo + error_msg "failed to tar" +} + +msg_3 "Renaming into: $(basename "$tar_name")" +mv "$f_tar_tmp" "$tar_name" || { + error_msg "Failed to rename: $f_tar_tmp" +} + +echo +echo "Saved as:" +echo "$tar_name" +echo diff --git a/tools/upgrade-aok-fs.sh b/tools/upgrade-aok-fs.sh index de1895f5..9e0fbbca 100755 --- a/tools/upgrade-aok-fs.sh +++ b/tools/upgrade-aok-fs.sh @@ -223,6 +223,13 @@ obsolete_files() { is_obsolete_file_present /etc/opt/AOK-login_method is_obsolete_file_present /etc/opt/hostname_cached + is_obsolete_file_present /etc/update-motd.d/11-aok-release + is_obsolete_file_present /etc/update-motd.d/12-deb-vers + is_obsolete_file_present /etc/update-motd.d/13-ish-release + is_obsolete_file_present /etc/update-motd.d/25-aok-release + is_obsolete_file_present /etc/update-motd.d/26-deb-vers + is_obsolete_file_present /etc/update-motd.d/27-ish-release + is_obsolete_file_present /usr/local/bin/aok_groups is_obsolete_file_present /usr/local/bin/apk_find_pkg is_obsolete_file_present /usr/local/bin/battery_charge @@ -350,3 +357,14 @@ check_softlinks # Double check that no new incompatiblities have been listed msg_2 "Ensuring no incompatabilies are detected" /usr/local/bin/check-env-compatible + +cmd_post_update=/etc/opt/AOK/post-update.sh + + +[ -x "$cmd_post_update" ] && { + msg_2 "Running $cmd_post_update" + $cmd_post_update +} + +echo +aok-versions diff --git a/tools/utils.sh b/tools/utils.sh index df706689..69737391 100644 --- a/tools/utils.sh +++ b/tools/utils.sh @@ -161,6 +161,14 @@ untar_file() { msg_3 " into: $(pwd)" fi + cmd_pigz="$(command -v pigz)" + + if [ -z "$cmd_pigz" ] && [ -x /home/linuxbrew/.linuxbrew/bin/pigz ]; then + cmd_pigz=/home/linuxbrew/.linuxbrew/bin/pigz + error_msg "><> using linuxbrew pigz [$cmd_pigz]" + fi + [ -z "$cmd_pigz" ] && error_msg "><> no pigz" + if [ -n "$cmd_pigz" ]; then # pigz -dc your_archive.tgz | tar -xf - msg_4 "Using $cmd_pigz" @@ -171,6 +179,7 @@ untar_file() { } else msg_4 "No pigz" + error_msg "><> No pigz [$cmd_pigz]" tar "xf${_tar_params}" "$_tarball" || { [ "$_no_exit" != "NO_EXIT_ON_ERROR" ] && error_msg "Failed to untar $_tarball" } @@ -460,21 +469,25 @@ copy_local_bins() { fi # msg_1 "Copying /usr/local stuff from $_clb_base_dir" - _clb_src_dir="/opt/AOK/${_clb_base_dir}/usr_local_bin" - if [ -z "$(find "$_clb_src_dir" -type d -empty)" ]; then - msg_3 "Add $_clb_base_dir AOK-FS stuff to /usr/local/bin" - mkdir -p /usr/local/bin - rsync_chown "$_clb_src_dir/*" /usr/local/bin silent + _clb_src_dir=/opt/AOK/"$_clb_base_dir" + + _clb_rel_src=usr_local_bin + _clb_dest=/usr/local/bin + msg_3 "><> ls $_clb_src_dir | grep -q $_clb_rel_src" + if find "$_clb_src_dir" | grep -q "$_clb_rel_src"; then + mkdir -p "$_clb_dest" + rsync_chown "$_clb_src_dir/$_clb_rel_src/*" "$_clb_dest" silent fi - _clb_src_dir="/opt/AOK/${_clb_base_dir}/usr_local_sbin" - if [ -d "$_clb_src_dir" ]; then - msg_3 "Add $_clb_base_dir AOK-FS stuff to /usr/local/sbin" - mkdir -p /usr/local/sbin - rsync_chown "$_clb_src_dir/*" /usr/local/sbin silent + _clb_rel_src=usr_local_sbin + _clb_dest=/usr/local/sbin + msg_3 "><> ls $_clb_src_dir | grep -q $_clb_rel_src" + if find "$_clb_src_dir" | grep -q "$_clb_rel_src"; then + mkdir -p "$_clb_dest" + rsync_chown "$_clb_src_dir/$_clb_rel_src/*" "$_clb_dest" silent fi - unset _clb_base_dir - unset _clb_src_dir + + unset _clb_base_dir _clb_src_dir _clb_rel_src _clb_dest # echo "^^^ copy_local_bins() - done" } @@ -1190,8 +1203,3 @@ f_logins_continous="$d_aok_etc"/login-continous f_hostname_aok_suffix="$d_aok_etc"/hostname-aok-suffix f_pts_0_as_console="$d_aok_etc"/pts_0_as_console f_profile_hints="$d_aok_etc"/show_profile_hints - -cmd_pigz="$(command -v pigz)" -if [ -z "$cmd_pigz" ] && [ -x /home/linuxbrew/.linuxbrew/bin/pigz ]; then - cmd_pigz=/home/linuxbrew/.linuxbrew/bin/pigz -fi diff --git a/tools/vers_check.sh b/tools/vers_check.sh index a96829c5..d5a760e2 100755 --- a/tools/vers_check.sh +++ b/tools/vers_check.sh @@ -37,25 +37,15 @@ min_version() { v_comp="$(get_digits_from_string "$1")" f_v_ref=/tmp/aok_vers_comp_ref - # echo "><> min_version($1) [$_aok_installed_alpine_vers]" - [ -z "$_aok_installed_alpine_vers" ] && { if [ -f "$f_v_ref" ]; then - # echo "><> will read cache file: $f_v_ref" _aok_installed_alpine_vers="$(cat "$f_v_ref")" - # echo "><> _aok_installed_alpine_vers [$_aok_installed_alpine_vers] from cache file: $f_v_ref" else _aok_installed_alpine_vers="$(get_digits_from_string "$(cat /etc/alpine-release)")" - # echo "><> _aok_installed_alpine_vers [$_aok_installed_alpine_vers] from /etc/alpine-release" - dirname "$f_v_ref" && { - # echo "><> will cache Alpine vers to $f_v_ref" - echo "$_aok_installed_alpine_vers" >"$f_v_ref" - } + echo "$_aok_installed_alpine_vers" >"$f_v_ref" fi } - # echo "><> will compare [$v_comp] -le [$_aok_installed_alpine_vers]" - # this only leaves _b defined [ "$v_comp" -le "$_aok_installed_alpine_vers" ] && _b=0 || _b=1 unset v_comp @@ -132,7 +122,6 @@ vers_check_verify() { v_ref="$2" v_comp="$3" - # echo "><> vers_check_verify($1,$2,$3)" min_version "$v_ref" "$v_comp" && rslt_actual=0 || rslt_actual=1 [ "$rslt_actual" = "$rslt_exp" ] || { echo "Failed: $v_ref <= $v_comp should be $rslt_exp - was $rslt_actual"