openvibers/openvibe.link Commits

Disable the Adeept stock server from crontab and rc.local autostart

OP OpenVibers committed 2 Oct 2026 · 2f6e87a0ee · 3 files, +204 −12

Asked: Make the installer disable the Adeept kit's stock control server on every autostart path the Adeept guide documents. Files: install/install.sh (stock-server handling starts around line 168: today it covers a systemd unit and running processes) and plugins/adeept_adr036/README.md (line 8 lists cron …
Harness job node-make-the-installer-disable-the-061604.

Changes

ddiff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
iindex da3f4be..2116e08 100644
---- a/.github/workflows/ci.yml
++++ b/.github/workflows/ci.yml
@@@ -79,4 +79,5 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
-- - run: shellcheck -s sh install/install.sh scripts/dist.sh
++ - run: shellcheck -s sh install/install.sh scripts/dist.sh scripts/test-install-stock-server.sh
++ - run: sh scripts/test-install-stock-server.sh
ddiff --git a/install/install.sh b/install/install.sh
iindex 8bb20dd..5603c73 100755
---- a/install/install.sh
++++ b/install/install.sh
@@@ -16,6 +16,12 @@
# Environment:
# OPENVIBE_NODE_BASE download base URL (default: GitHub releases of OpenVibers/OpenVibe.Node).
# OPENVIBE_SERVER OpenVibe.Bot origin (default https://openvibe.bot).
++#
++# The Adeept stock-server check can be pointed at plain files for testing (no root, no crontab command):
++# OPENVIBE_INSTALL_STOCK_ONLY=1 run only that check and exit.
++# OPENVIBE_CRONTAB_ROOT=FILE edit FILE as root's crontab instead of the real one.
++# OPENVIBE_CRONTAB_USER=FILE edit FILE as the invoking user's crontab instead of the real one.
++# OPENVIBE_RC_LOCAL=FILE edit FILE as rc.local instead of /etc/rc.local.
set -eu
REPO_URL="https://github.com/OpenVibers/OpenVibe.Node"
@@@ -49,6 +55,102 @@ case "$ROBOT" in adeept|adeept-mecanum|cozmo|none) ;; *) die "--robot must be ad
# Root for the service, /usr/local/bin and /etc.
SUDO=""
++
++# ---- the Adeept kit's stock server: never run it (fixed admin:123456 login on 0.0.0.0:8888, MJPEG on :5000) ----
++# Its installer autostarts it from the user's crontab (or root's, with an @reboot line) or from /etc/rc.local,
++# depending on kit version. Besides the systemd unit and any running process, comment out those autostart lines
++# (marked, never deleted) so they cannot start it again.
++STOCK_SERVER_RE='Server_(Ordinary|Mecanum)Wheels/(WebServer|APPServer|GUIServer|app)\.py'
++STOCK_SERVER_MARKER='#openvibe-node-disabled:'
++CRON_USER="${SUDO_USER:-$(id -un 2>/dev/null || printf '%s' root)}"
++
++# Comment out the stock-server lines in one crontab-like file: read $1, write $2, print one line per disabled
++# entry. A line whose first non-blank character is "#" is left alone, so our marker makes a second run a no-op.
++disable_stock_lines() {
++ _src="$1" _dst="$2" _where="$3"
++ : > "$_dst"
++ while IFS= read -r _line || [ -n "$_line" ]; do
++ _trim="${_line#"${_line%%[![:space:]]*}"}"
++ if [ "${_trim#\#}" = "$_trim" ] && printf '%s\n' "$_line" | grep -Eq "$STOCK_SERVER_RE"; then
++ printf '%s %s\n' "$STOCK_SERVER_MARKER" "$_line" >> "$_dst"
++ say "disabled the Adeept kit's stock server autostart in $_where"
++ else
++ printf '%s\n' "$_line" >> "$_dst"
++ fi
++ done < "$_src"
++}
++
++# Edit a plain crontab-like file in place (the test-override paths). No crontab command and no sudo.
++disable_stock_file() {
++ _file="$1" _where="$2"
++ [ -f "$_file" ] || return 0
++ _before="$(mktemp)" _after="$(mktemp)"
++ cp "$_file" "$_before"
++ disable_stock_lines "$_before" "$_after" "$_where"
++ if ! cmp -s "$_before" "$_after"; then cp "$_after" "$_file"; fi
++ rm -f "$_before" "$_after"
++}
++
++# Comment out stock-server lines in one user's crontab and reinstall it only if it changed.
++disable_stock_crontab() {
++ _user="$1"
++ command -v crontab >/dev/null 2>&1 || return 0
++ _before="$(mktemp)" _after="$(mktemp)"
++ $SUDO crontab -u "$_user" -l > "$_before" 2>/dev/null || true
++ if [ ! -s "$_before" ]; then rm -f "$_before" "$_after"; return 0; fi
++ disable_stock_lines "$_before" "$_after" "the crontab of $_user"
++ if ! cmp -s "$_before" "$_after"; then $SUDO crontab -u "$_user" "$_after" || true; fi
++ rm -f "$_before" "$_after"
++}
++
++# Comment out stock-server lines in rc.local (the real path; needs root to write it back).
++disable_stock_rc_local() {
++ _rc="$1"
++ [ -f "$_rc" ] || return 0
++ _before="$(mktemp)" _after="$(mktemp)"
++ $SUDO cp "$_rc" "$_before" 2>/dev/null || { rm -f "$_before" "$_after"; return 0; }
++ disable_stock_lines "$_before" "$_after" "$_rc"
++ if ! cmp -s "$_before" "$_after"; then $SUDO cp "$_after" "$_rc" || true; fi
++ rm -f "$_before" "$_after"
++}
++
++disable_stock_server() {
++ if command -v systemctl >/dev/null 2>&1; then
++ unit=Adeept_Robot.service
++ if systemctl is-enabled "$unit" >/dev/null 2>&1 || systemctl is-active "$unit" >/dev/null 2>&1; then
++ say "disabling the Adeept kit's stock server ($unit): it listens on 0.0.0.0:8888 with a fixed password"
++ $SUDO systemctl disable --now "$unit" || true
++ fi
++ fi
++ if command -v pgrep >/dev/null 2>&1 && pgrep -f "$STOCK_SERVER_RE" >/dev/null 2>&1; then
++ say "stopping a running Adeept stock server process"
++ $SUDO pkill -f "$STOCK_SERVER_RE" || true
++ fi
++ # Autostart: root's crontab and the invoking user's, then rc.local. OPENVIBE_CRONTAB_* / OPENVIBE_RC_LOCAL
++ # are test-only file overrides so the checks can run without root and without touching the real system.
++ if [ -n "${OPENVIBE_CRONTAB_ROOT:-}" ]; then
++ disable_stock_file "$OPENVIBE_CRONTAB_ROOT" "the root crontab"
++ else
++ disable_stock_crontab root
++ fi
++ if [ -n "${OPENVIBE_CRONTAB_USER:-}" ]; then
++ disable_stock_file "$OPENVIBE_CRONTAB_USER" "the crontab of $CRON_USER"
++ elif [ "$CRON_USER" != root ]; then
++ disable_stock_crontab "$CRON_USER"
++ fi
++ if [ -n "${OPENVIBE_RC_LOCAL:-}" ]; then
++ disable_stock_file "$OPENVIBE_RC_LOCAL" "rc.local ($OPENVIBE_RC_LOCAL)"
++ else
++ disable_stock_rc_local /etc/rc.local
++ fi
++}
++
++# Test hook: run only the stock-server check against the OPENVIBE_* file overrides, then stop.
++if [ "${OPENVIBE_INSTALL_STOCK_ONLY:-0}" = 1 ]; then
++ disable_stock_server
++ exit 0
++fi
++
if [ "$(id -u)" -ne 0 ]; then
command -v sudo >/dev/null 2>&1 || die "run as root (sudo is not installed)"
SUDO="sudo"
@@@ -166,17 +268,7 @@ else
fi
# ---- the Adeept kit's stock server: never run it (fixed admin:123456 login on 0.0.0.0:8888, MJPEG on :5000) ----
--if command -v systemctl >/dev/null 2>&1; then
-- unit=Adeept_Robot.service
-- if systemctl is-enabled "$unit" >/dev/null 2>&1 || systemctl is-active "$unit" >/dev/null 2>&1; then
-- say "disabling the Adeept kit's stock server ($unit): it listens on 0.0.0.0:8888 with a fixed password"
-- $SUDO systemctl disable --now "$unit" || true
-- fi
--fi
--if command -v pgrep >/dev/null 2>&1 && pgrep -f "Server_(Ordinary|Mecanum)Wheels/(WebServer|APPServer|GUIServer|app)\.py" >/dev/null 2>&1; then
-- say "stopping a running Adeept stock server process"
-- $SUDO pkill -f "Server_(Ordinary|Mecanum)Wheels/(WebServer|APPServer|GUIServer|app)\.py" || true
--fi
++disable_stock_server
# ---- service ----
if [ "$SERVICE" = 1 ]; then
ddiff --git a/scripts/test-install-stock-server.sh b/scripts/test-install-stock-server.sh
nnew file mode 100644
iindex 0000000..63e75c9
---- /dev/null
++++ b/scripts/test-install-stock-server.sh
@@@ -0,0 +1,99 @@
++#!/bin/sh
++# Tests install.sh's handling of the Adeept kit's stock-server autostart: crontab (root's and the invoking
++# user's, including @reboot lines) and /etc/rc.local. The OPENVIBE_* test overrides point the checks at files in
++# a temp dir, so this needs no root and touches no real crontab or /etc/rc.local.
++set -eu
++
++here="$(cd "$(dirname "$0")" && pwd)"
++installer="$here/../install/install.sh"
++
++fail() { printf 'FAIL: %s\n' "$*" >&2; exit 1; }
++
++tmp="$(mktemp -d)"
++trap 'rm -rf "$tmp"' EXIT
++root_cron="$tmp/root-crontab"
++user_cron="$tmp/user-crontab"
++rc_local="$tmp/rc.local"
++
++cat > "$root_cron" <<'EOF'
++# root's crontab
++PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
++@reboot python3 /home/pi/adeept_awr/Server/Server_OrdinaryWheels/WebServer.py
++0 4 * * * /usr/bin/backup.sh
++EOF
++
++cat > "$user_cron" <<'EOF'
++@reboot python3 /home/pi/adeept_awr/Server/Server_OrdinaryWheels/app.py
++*/5 * * * * /home/pi/adeept_awr/Server/Server_OrdinaryWheels/helper.py
++EOF
++
++cat > "$rc_local" <<'EOF'
++#!/bin/sh -e
++python3 /home/pi/adeept_awr/Server/Server_MecanumWheels/WebServer.py &
++/usr/local/bin/other-thing &
++exit 0
++EOF
++
++run() {
++ OPENVIBE_INSTALL_STOCK_ONLY=1 \
++ OPENVIBE_CRONTAB_ROOT="$root_cron" \
++ OPENVIBE_CRONTAB_USER="$user_cron" \
++ OPENVIBE_RC_LOCAL="$rc_local" \
++ sh "$installer"
++}
++
++out="$(run)"
++printf '%s\n' "$out"
++
++# One line per disabled thing.
++disabled="$(printf '%s\n' "$out" | grep -c "stock server autostart" || true)"
++[ "$disabled" = 3 ] || fail "expected 3 disabled lines, got $disabled"
++
++# The stock lines are commented out with the marker, not deleted.
++grep -q '^#openvibe-node-disabled: @reboot python3 /home/pi/adeept_awr/Server/Server_OrdinaryWheels/WebServer\.py$' "$root_cron" ||
++ fail "root crontab stock line not commented out"
++grep -q '^#openvibe-node-disabled: @reboot python3 /home/pi/adeept_awr/Server/Server_OrdinaryWheels/app\.py$' "$user_cron" ||
++ fail "user crontab @reboot stock line not commented out"
++grep -q '^#openvibe-node-disabled: python3 /home/pi/adeept_awr/Server/Server_MecanumWheels/WebServer\.py &$' "$rc_local" ||
++ fail "rc.local stock line not commented out"
++
++# Unrelated lines are untouched.
++grep -qx '0 4 \* \* \* /usr/bin/backup.sh' "$root_cron" || fail "unrelated root crontab line changed"
++grep -qx 'PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin' "$root_cron" || fail "root crontab PATH line changed"
++grep -qxF "# root's crontab" "$root_cron" || fail "root crontab comment changed"
++grep -qx '\*/5 \* \* \* \* /home/pi/adeept_awr/Server/Server_OrdinaryWheels/helper.py' "$user_cron" ||
++ fail "unrelated user crontab line changed"
++grep -qx '/usr/local/bin/other-thing &' "$rc_local" || fail "unrelated rc.local line changed"
++grep -qx 'exit 0' "$rc_local" || fail "rc.local exit line changed"
++
++# No stock-server line is left active.
++if grep -Eq '^[[:space:]]*[^#[:space:]].*Server_(Ordinary|Mecanum)Wheels/(WebServer|APPServer|GUIServer|app)\.py' \
++ "$root_cron" "$user_cron" "$rc_local"; then
++ fail "a stock-server line is still active"
++fi
++
++# A second run is a no-op: nothing reported and nothing changed.
++cp "$root_cron" "$tmp/root.before"
++cp "$user_cron" "$tmp/user.before"
++cp "$rc_local" "$tmp/rc.before"
++out2="$(run)"
++printf '%s\n' "$out2"
++if printf '%s\n' "$out2" | grep -q "stock server autostart"; then fail "second run reported more changes"; fi
++cmp -s "$root_cron" "$tmp/root.before" || fail "second run changed the root crontab"
++cmp -s "$user_cron" "$tmp/user.before" || fail "second run changed the user crontab"
++cmp -s "$rc_local" "$tmp/rc.before" || fail "second run changed rc.local"
++
++# A host without the kit: unrelated crontab/rc.local content is left alone and nothing is reported.
++none="$tmp/none"
++mkdir -p "$none"
++printf '0 5 * * * /usr/bin/echo hello\n' > "$none/cron"
++printf 'PATH=/bin\n' > "$none/cron2"
++printf '#!/bin/sh\nexit 0\n' > "$none/rc"
++out3="$(OPENVIBE_INSTALL_STOCK_ONLY=1 OPENVIBE_CRONTAB_ROOT="$none/cron" OPENVIBE_CRONTAB_USER="$none/cron2" \
++ OPENVIBE_RC_LOCAL="$none/rc" sh "$installer")"
++printf '%s\n' "$out3"
++if printf '%s\n' "$out3" | grep -q "stock server"; then fail "reported changes on a host without the kit"; fi
++grep -qx '0 5 \* \* \* /usr/bin/echo hello' "$none/cron" || fail "unrelated cron line changed without the kit"
++grep -qx '#!/bin/sh' "$none/rc" || fail "unrelated rc.local changed without the kit"
++
++printf 'ok: install.sh stock-server crontab/rc.local handling\n'