overthesun / simoc-sam

Back-end system to support SIMOC Live air quality monitor sensor array as used at the SAM Mars habitat analog.
https://samb2.space/
2 stars 1 forks source link

Automatically launch `tmux` on boot #110

Open ezio-melotti opened 3 months ago

ezio-melotti commented 3 months ago

In case of power outage, the RPis might reboot. Currently, if that happens, we have to SSH into each one of them and manually relaunch tmux. This should be automated, however:

  1. launching tmux from rc.local doesn't seem to work;
  2. launching the processes directly works, but it doesn't provide us the ability to see their output conveniently like tmux does.

It should however be possible to define a systemd service that starts the tmux session on boot.

ezio-melotti commented 3 months ago

I looked into this but couldn't find a way to make it work. Here are some notes.

I created this file:

# tmux/sam-tmux.service
[Unit]
Description=Start tmux session at boot
After=network.target

[Service]
User=pi
Type=oneshot
ExecStart=python3 /home/pi/simoc-sam/simoc-sam.py run-tmux
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

I also tried Type=forking instead of oneshot

I set it as executable with chmod +x tmux/sam-tmux.service. I symlinked it with sudo ln -s /home/pi/simoc-sam/tmux/sam-tmux.service /etc/systemd/system/sam-tmux.service. I enabled the service with sudo systemctl enable sam-tmux.service and started it with sudo systemctl start sam-tmux.service. I used restart after making changes. I used status or journalctl -u sam-tmux.service -b to see the logs.

I made the following changes in simoc-sam.py:

@@ -40,10 +40,11 @@ def cmd(func):
 def run(args):
     print('>>', ' '.join(args))
     print('-'*80)
-    result = subprocess.run(args)
+    result = subprocess.run(args, capture_output=True)
     print('-'*80)
     print('<<', result)
     print()
+    print(result.stderr.decode())
     return not result.returncode

This shows the stderr output of the executed commands.

@@ -287,10 +288,10 @@ def run_server():
 def run_tmux(file='mqtt'):
     """Launch a tmux script (or attach to an existing session)."""
     if run(['tmux', 'has-session', '-t', TMUX_SNAME]):
-        run(['tmux', 'attach-session', '-t', TMUX_SNAME])  # attach to sessions
+        return run(['tmux', 'attach-session', '-t', TMUX_SNAME])  # attach to sessions
     else:
         tmux_path = SIMOC_SAM_DIR / 'tmux' / f'{file}.sh'
-        run([str(tmux_path), TMUX_SNAME])  # start new sessions
+        return run([str(tmux_path), TMUX_SNAME])  # start new sessions

This ensures that the exit status of simoc-sam.py is correct (should be done to the other commands too).

I also updated tmux/mqtt.sh to correctly start the venv:

In tmux/mqtt.sh:

-tmux new-session -s $SNAME -d -x "$(tput cols)" -y "$(tput lines)"
-# The first pane is just a shell
+#tmux new-session -s $SNAME -d -x "$(tput cols)" -y "$(tput lines)"
+echo 'starting new session' >&2
+tmux new-session -s $NAME -d
+# The first pane is just a shell
+echo 'sending keys' >&2

This adds debug prints to stderr and removes tputs (that don't work).

The command still fails with:

starting new session
open terminal failed: not a terminal
sending keys
no server running on /tmp/tmux-1000/default

The last message is repeated for any other command in mqtt.sh.

ezio-melotti commented 3 months ago

In #112 I went for a different approach that doesn't require tmux. However it should be possible to create two systemd services: one that runs the tmux server, and the other that connects to it.

I haven't tried this approach, since the solution proposed in #112 is cleaner.