openvibers/openvibe.link Commits
Scan root and pi crontabs, skip service checks under test overrides (#7)
Changes
@@@ -117,8 +117,12 @@ Raspberry Pi OS Bookworm (64-bit recommended). Enable I²C and SPI: `sudo raspi-`--driver adeept` (or `adeept-mecanum`).The kit's own software (`Adeept_Robot.service`, `WebServer.py` on `0.0.0.0:8888` with the fixed login--`admin:123456`, MJPEG on `:5000`) must not run: anyone on the network could drive the car. The installer disables it;--check with `systemctl status Adeept_Robot.service`. The Node replaces it.++`admin:123456`, MJPEG on `:5000`) must not run: anyone on the network could drive the car. The installer disables it,++including autostart lines in root's and the invoking user's crontabs and `/etc/rc.local`. From a root shell, it checks++`pi`'s crontab when that account exists. It comments out the kit's lines with the marker++`#openvibe-node-disabled:` and keeps the original text, so running the installer again changes nothing. Check with++`systemctl status Adeept_Robot.service`, `crontab -l` (and `sudo crontab -l -u pi` for a root-shell install) and++`grep openvibe-node-disabled /etc/rc.local`. The Node replaces it.If a direction is wrong on your car, fix it in `config.json` → `plugins[0].config`: `motors.<wheel>.direction`,`pan.invert`, `tilt.invert`, `line.invert`. See [the plugin README](../plugins/adeept_adr036/README.md).@@@ -84,7 +84,10 @@ SUDO=""# (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:'++# Root's crontab is always scanned. Scan the invoking user's crontab on the normal install path or through sudo.++# From a plain root shell (sudo -i, root login), use the kit's usual owner pi when that account exists.CRON_USER="${SUDO_USER:-$(id -un 2>/dev/null || printf '%s' root)}"++if [ "$CRON_USER" = root ] && id pi >/dev/null 2>&1; then CRON_USER=pi; fi# 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.@@@ -137,16 +140,20 @@ disable_stock_rc_local() {}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++ # The OPENVIBE_* file overrides are test-only: when any is set they point the crontab/rc.local checks at temp++ # files, so skip the real systemd and running-process branches too (a test must touch no service or process).++ if [ -z "${OPENVIBE_CRONTAB_ROOT:-}${OPENVIBE_CRONTAB_USER:-}${OPENVIBE_RC_LOCAL:-}" ]; then++ 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" || truefi-- 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" || truefi# 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.@@@ -156,8 +163,8 @@ disable_stock_server() {disable_stock_crontab rootfiif [ -n "${OPENVIBE_CRONTAB_USER:-}" ]; then-- disable_stock_file "$OPENVIBE_CRONTAB_USER" "the crontab of $CRON_USER"-- elif [ "$CRON_USER" != root ]; then++ disable_stock_file "$OPENVIBE_CRONTAB_USER" "the crontab of ${CRON_USER:-$(id -un 2>/dev/null || printf '%s' root)}"++ elif [ -n "$CRON_USER" ] && [ "$CRON_USER" != root ]; thendisable_stock_crontab "$CRON_USER"fiif [ -n "${OPENVIBE_RC_LOCAL:-}" ]; then@@@ -8,8 +8,12 @@ kit's code is imported.## Keep the kit's stock server disabledThe kit's own server listens on `0.0.0.0:8888` with the fixed login `admin` / `123456` and streams MJPEG on `:5000`.--Anyone on the network could drive the car with it. Disable its autostart (the kit installer adds it to the user's--crontab or `/etc/rc.local`, depending on version) and do not run it next to the Node. This plugin never starts it.++Anyone on the network could drive the car with it. The installer disables its autostart in root's and the invoking++user's crontabs and `/etc/rc.local`. From a root shell, it checks `pi`'s crontab when that account exists. It comments++out the kit's lines with the marker `#openvibe-node-disabled:` and keeps the original text, so running the installer++again changes nothing. Check with `systemctl status Adeept_Robot.service`, `crontab -l` (and++`sudo crontab -l -u pi` for a root-shell install) and++`grep openvibe-node-disabled /etc/rc.local`. Do not run it next to the Node. This plugin never starts it.## Wiring (kit defaults)@@@ -1,7 +1,7 @@#!/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.++# a temp dir, so this needs no root and touches no real crontab, rc.local, service or process.set -euhere="$(cd "$(dirname "$0")" && pwd)"@@@ -96,4 +96,37 @@ if printf '%s\n' "$out3" | grep -q "stock server"; then fail "reported changes ogrep -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"++# Without SUDO_USER, the normal install path must still scan the logged-in user's crontab. Mock the system commands++# so this checks user selection without touching any real crontab, even when CI runs as root.++mock_bin="$tmp/mock-bin"++mkdir -p "$mock_bin"++cat > "$mock_bin/id" <<'EOF'++#!/bin/sh++case "$1" in++ -un) printf '%s\n' invoking_user ;;++ pi) exit 1 ;;++ *) exit 1 ;;++esac++EOF++cat > "$mock_bin/crontab" <<'EOF'++#!/bin/sh++[ "$1" = -u ] && [ "$2" = invoking_user ] || exit 1++case "$3" in++ -l) cat "$MOCK_USER_CRON" ;;++ *) cp "$3" "$MOCK_USER_CRON" ;;++esac++EOF++chmod +x "$mock_bin/id" "$mock_bin/crontab"++fallback_cron="$tmp/fallback-crontab"++printf '%s\n' '@reboot python3 /home/pi/adeept_awr/Server/Server_OrdinaryWheels/WebServer.py' > "$fallback_cron"++out4="$(++ unset SUDO_USER++ PATH="$mock_bin:$PATH" MOCK_USER_CRON="$fallback_cron" OPENVIBE_INSTALL_STOCK_ONLY=1 \++ OPENVIBE_CRONTAB_ROOT="$root_cron" OPENVIBE_CRONTAB_USER='' OPENVIBE_RC_LOCAL="$rc_local" sh "$installer"++)"++printf '%s\n' "$out4" | grep -q 'stock server autostart in the crontab of invoking_user' ||++ fail "logged-in user's crontab was not scanned without SUDO_USER"++grep -q '^#openvibe-node-disabled: @reboot python3 /home/pi/adeept_awr/Server/Server_OrdinaryWheels/WebServer\.py$' \++ "$fallback_cron" || fail "logged-in user's stock line was not commented out"++printf 'ok: install.sh stock-server crontab/rc.local handling\n'
@@ -117,8 +117,12 @@ Raspberry Pi OS Bookworm (64-bit recommended). Enable I²C and SPI: `sudo raspi-
@@ -117,8 +117,12 @@ Raspberry Pi OS Bookworm (64-bit recommended). Enable I²C and SPI: `sudo raspi-
`--driver adeept` (or `adeept-mecanum`).
`--driver adeept` (or `adeept-mecanum`).
The kit's own software (`Adeept_Robot.service`, `WebServer.py` on `0.0.0.0:8888` with the fixed login
The kit's own software (`Adeept_Robot.service`, `WebServer.py` on `0.0.0.0:8888` with the fixed login
-`admin:123456`, MJPEG on `:5000`) must not run: anyone on the network could drive the car. The installer disables it;
-check with `systemctl status Adeept_Robot.service`. The Node replaces it.
+`admin:123456`, MJPEG on `:5000`) must not run: anyone on the network could drive the car. The installer disables it,
+including autostart lines in root's and the invoking user's crontabs and `/etc/rc.local`. From a root shell, it checks
+`pi`'s crontab when that account exists. It comments out the kit's lines with the marker
+`#openvibe-node-disabled:` and keeps the original text, so running the installer again changes nothing. Check with
+`systemctl status Adeept_Robot.service`, `crontab -l` (and `sudo crontab -l -u pi` for a root-shell install) and
+`grep openvibe-node-disabled /etc/rc.local`. The Node replaces it.
If a direction is wrong on your car, fix it in `config.json` → `plugins[0].config`: `motors.<wheel>.direction`,
If a direction is wrong on your car, fix it in `config.json` → `plugins[0].config`: `motors.<wheel>.direction`,
`pan.invert`, `tilt.invert`, `line.invert`. See [the plugin README](../plugins/adeept_adr036/README.md).
`pan.invert`, `tilt.invert`, `line.invert`. See [the plugin README](../plugins/adeept_adr036/README.md).
@@ -84,7 +84,10 @@ SUDO=""
@@ -84,7 +84,10 @@ SUDO=""
# (marked, never deleted) so they cannot start it again.
# (marked, never deleted) so they cannot start it again.
STOCK_SERVER_RE='Server_(Ordinary|Mecanum)Wheels/(WebServer|APPServer|GUIServer|app)\.py'
STOCK_SERVER_RE='Server_(Ordinary|Mecanum)Wheels/(WebServer|APPServer|GUIServer|app)\.py'
STOCK_SERVER_MARKER='#openvibe-node-disabled:'
STOCK_SERVER_MARKER='#openvibe-node-disabled:'
+# Root's crontab is always scanned. Scan the invoking user's crontab on the normal install path or through sudo.
+# From a plain root shell (sudo -i, root login), use the kit's usual owner pi when that account exists.
CRON_USER="${SUDO_USER:-$(id -un 2>/dev/null || printf '%s' root)}"
CRON_USER="${SUDO_USER:-$(id -un 2>/dev/null || printf '%s' root)}"
+if [ "$CRON_USER" = root ] && id pi >/dev/null 2>&1; then CRON_USER=pi; fi
# Comment out the stock-server lines in one crontab-like file: read $1, write $2, print one line per disabled
# 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.
# entry. A line whose first non-blank character is "#" is left alone, so our marker makes a second run a no-op.
@@ -137,16 +140,20 @@ disable_stock_rc_local() {
@@ -137,16 +140,20 @@ disable_stock_rc_local() {
}
}
disable_stock_server() {
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
+ # The OPENVIBE_* file overrides are test-only: when any is set they point the crontab/rc.local checks at temp
+ # files, so skip the real systemd and running-process branches too (a test must touch no service or process).
+ if [ -z "${OPENVIBE_CRONTAB_ROOT:-}${OPENVIBE_CRONTAB_USER:-}${OPENVIBE_RC_LOCAL:-}" ]; then
+ 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
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
fi
# Autostart: root's crontab and the invoking user's, then rc.local. OPENVIBE_CRONTAB_* / OPENVIBE_RC_LOCAL
# 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.
# are test-only file overrides so the checks can run without root and without touching the real system.
@@ -156,8 +163,8 @@ disable_stock_server() {
@@ -156,8 +163,8 @@ disable_stock_server() {
disable_stock_crontab root
disable_stock_crontab root
fi
fi
if [ -n "${OPENVIBE_CRONTAB_USER:-}" ]; then
if [ -n "${OPENVIBE_CRONTAB_USER:-}" ]; then
- disable_stock_file "$OPENVIBE_CRONTAB_USER" "the crontab of $CRON_USER"
- elif [ "$CRON_USER" != root ]; then
+ disable_stock_file "$OPENVIBE_CRONTAB_USER" "the crontab of ${CRON_USER:-$(id -un 2>/dev/null || printf '%s' root)}"
+ elif [ -n "$CRON_USER" ] && [ "$CRON_USER" != root ]; then
disable_stock_crontab "$CRON_USER"
disable_stock_crontab "$CRON_USER"
fi
fi
if [ -n "${OPENVIBE_RC_LOCAL:-}" ]; then
if [ -n "${OPENVIBE_RC_LOCAL:-}" ]; then
@@ -8,8 +8,12 @@ kit's code is imported.
@@ -8,8 +8,12 @@ kit's code is imported.
## Keep the kit's stock server disabled
## Keep the kit's stock server disabled
The kit's own server listens on `0.0.0.0:8888` with the fixed login `admin` / `123456` and streams MJPEG on `:5000`.
The kit's own server listens on `0.0.0.0:8888` with the fixed login `admin` / `123456` and streams MJPEG on `:5000`.
-Anyone on the network could drive the car with it. Disable its autostart (the kit installer adds it to the user's
-crontab or `/etc/rc.local`, depending on version) and do not run it next to the Node. This plugin never starts it.
+Anyone on the network could drive the car with it. The installer disables its autostart in root's and the invoking
+user's crontabs and `/etc/rc.local`. From a root shell, it checks `pi`'s crontab when that account exists. It comments
+out the kit's lines with the marker `#openvibe-node-disabled:` and keeps the original text, so running the installer
+again changes nothing. Check with `systemctl status Adeept_Robot.service`, `crontab -l` (and
+`sudo crontab -l -u pi` for a root-shell install) and
+`grep openvibe-node-disabled /etc/rc.local`. Do not run it next to the Node. This plugin never starts it.
## Wiring (kit defaults)
## Wiring (kit defaults)
@@ -1,7 +1,7 @@
@@ -1,7 +1,7 @@
#!/bin/sh
#!/bin/sh
# Tests install.sh's handling of the Adeept kit's stock-server autostart: crontab (root's and the invoking
# 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
# 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.
+# a temp dir, so this needs no root and touches no real crontab, rc.local, service or process.
set -eu
set -eu
here="$(cd "$(dirname "$0")" && pwd)"
here="$(cd "$(dirname "$0")" && pwd)"
@@ -96,4 +96,37 @@ if printf '%s\n' "$out3" | grep -q "stock server"; then fail "reported changes o
@@ -96,4 +96,37 @@ if printf '%s\n' "$out3" | grep -q "stock server"; then fail "reported changes o
grep -qx '0 5 \* \* \* /usr/bin/echo hello' "$none/cron" || fail "unrelated cron line changed without the kit"
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"
grep -qx '#!/bin/sh' "$none/rc" || fail "unrelated rc.local changed without the kit"
+# Without SUDO_USER, the normal install path must still scan the logged-in user's crontab. Mock the system commands
+# so this checks user selection without touching any real crontab, even when CI runs as root.
+mock_bin="$tmp/mock-bin"
+mkdir -p "$mock_bin"
+cat > "$mock_bin/id" <<'EOF'
+#!/bin/sh
+case "$1" in
+ -un) printf '%s\n' invoking_user ;;
+ pi) exit 1 ;;
+ *) exit 1 ;;
+esac
+EOF
+cat > "$mock_bin/crontab" <<'EOF'
+#!/bin/sh
+[ "$1" = -u ] && [ "$2" = invoking_user ] || exit 1
+case "$3" in
+ -l) cat "$MOCK_USER_CRON" ;;
+ *) cp "$3" "$MOCK_USER_CRON" ;;
+esac
+EOF
+chmod +x "$mock_bin/id" "$mock_bin/crontab"
+fallback_cron="$tmp/fallback-crontab"
+printf '%s\n' '@reboot python3 /home/pi/adeept_awr/Server/Server_OrdinaryWheels/WebServer.py' > "$fallback_cron"
+out4="$(
+ unset SUDO_USER
+ PATH="$mock_bin:$PATH" MOCK_USER_CRON="$fallback_cron" OPENVIBE_INSTALL_STOCK_ONLY=1 \
+ OPENVIBE_CRONTAB_ROOT="$root_cron" OPENVIBE_CRONTAB_USER='' OPENVIBE_RC_LOCAL="$rc_local" sh "$installer"
+)"
+printf '%s\n' "$out4" | grep -q 'stock server autostart in the crontab of invoking_user' ||
+ fail "logged-in user's crontab was not scanned without SUDO_USER"
+grep -q '^#openvibe-node-disabled: @reboot python3 /home/pi/adeept_awr/Server/Server_OrdinaryWheels/WebServer\.py$' \
+ "$fallback_cron" || fail "logged-in user's stock line was not commented out"
+
printf 'ok: install.sh stock-server crontab/rc.local handling\n'
printf 'ok: install.sh stock-server crontab/rc.local handling\n'