Anyone can suggest why sysupgrade fails when called from a script on OpenWrt backfire?

I'm working on upgrading a fleet of devices which unfortunately are running OpenWRT backfire (there are many different OpenWRT versions used, but the majority of the devices is running Backfire).

For this task I'm using OpenWISP Firmware Upgrader, which I built.
The automated procedures won't work on Backfire, initially I thought it was a python issue, but this shell command yields the same result:

ssh root@<ip> -T "/sbin/sysupgrade -v -n /tmp/*.bin"

The result I get is the following:

/sbin/sysupgrade: line 145: pivot_root: not found
umount: can't umount /tmp/root: Device or resource busy
umount: can't umount /tmp/root: Device or resource busy
Switching to ramdisk...
Failed to switch over to ramfs. Please reboot.

However, if I log in via SSH and then run: /sbin/sysupgrade -v -n /tmp/*.bin, it works:

/sbin/sysupgrade -v -n /tmp/*.bin
Switching to ramdisk...
Performing system upgrade...
Unlocking firmware ...
Writing from <stdin> to firmware ...  [w]

I can't understand why sysupgrade doesn't work when called from a script while it does when called from an interactive shell session, before giving up and update all the devices manually I'd like to know if I can trick it to believe it's an interactive shell session or something like that.

Compare the environment (env | sort > /tmp/env.txt) between interactive and noninteractive sessions. Iirc, pivot_root is a busybox applet which needs to be copied to the ramdisk by sysupgrade. Maybe this tool is skipped because $PATH is improperly set or due to some other reason.

Also try running /sbin/sysupgrade under sh -x to see what it is doing exactly when being invoked non-interactively.

3 Likes

The env is indeed different, the PATH seems to be missing a few direcotries.

ENV from non interactive shell:

HOME=/root
LOGNAME=root
PATH=/usr/bin:/bin
PWD=/root
SHELL=/bin/ash
SSH_CONNECTION=10.8.0.1 39142 10.8.0.5 22
USER=root

ENV from interactive shell:

HOME=/root
LOGNAME=root
PATH=/bin:/sbin:/usr/bin:/usr/sbin
PS1=\u@\h:\w\$ 
PWD=/root
SHELL=/bin/ash
SSH_CONNECTION=10.8.0.1 36496 10.8.0.5 22
SSH_TTY=/dev/pts/0
TERM=xterm-256color
USER=root

Supplying the PATH like following has worked:

root@<ip> -T "export PATH=/bin:/sbin:/usr/bin:/usr/sbin; sysupgrade -v -n /tmp/*bin"

Thanks a lot @jow!