Telegram bots can show a command menu when users type / in a chat. Registering commands is a single API call — no approval, no webhook setup, no special bot-side handling.
curl -s -X POST "https://api.telegram.org/bot<TOKEN>/setMyCommands" \
-H "Content-Type: application/json" \
-d '{"commands": [
{"command": "status", "description": "Show active host"},
{"command": "switch", "description": "Switch active host"}
]}'
From the bot's perspective, /status or /switch desktop arrives as plain text in message.text — you parse it like any other message.
Scope-aware deletion
deleteMyCommands supports optional scope and language_code parameters so you can clear commands for specific contexts (private chats, groups, a single chat, a specific language). But there's no API to delete individual commands.
The elegant part: setMyCommands always does a full overwrite. Sending an empty array clears everything:
# These are equivalent:
curl -s -X POST "https://api.telegram.org/bot<TOKEN>/setMyCommands" \
-d '{"commands": []}'
curl -s -X POST "https://api.telegram.org/bot<TOKEN>/deleteMyCommands"
To remove a single command, just setMyCommands with the updated list minus the one you want gone. The overwrite-everything semantics means there's no "add" or "remove" — only "set the complete list." deleteMyCommands is a convenience method, not a necessity.
If you're still using terminal tabs, tmux windows do the same job with extras you didn't know you needed.
The hierarchy: Session > Window > Pane. A session holds multiple windows, each window can be split into panes. The bottom status bar shows all windows at a glance:
[main] 0:bash* 1:vim- 2:server
* marks the active window, - marks the previous one. You always know where you are.
Key bindings to internalize:
| Action |
Key |
| New window |
Ctrl+b c |
| Next window |
Ctrl+b n |
| Previous window |
Ctrl+b p |
| Jump by number |
Ctrl+b 0~9 |
| List all windows |
Ctrl+b w |
| Rename window |
Ctrl+b , |
What tmux gives you over plain terminal tabs:
- Survives disconnects — SSH drops? Reconnect with
tmux attach, everything is still there. Terminal tabs are gone the moment the connection dies.
- Panes — Split any window horizontally or vertically without opening another tab.
- Scriptable — Create and arrange windows/panes from a script or config.
The one real risk: if the machine itself reboots, the session is gone. tmux-resurrect and tmux-continuum can save/restore layouts, but in practice most people use tmux to survive network hiccups, not server reboots. A reboot means re-opening a session, which takes seconds.
Both prevent a process from dying when you close the terminal, but they work at different stages and with different guarantees.
nohup intervenes before launch. It sets the process itself to ignore SIGHUP via sigaction, so no matter who sends the signal, the process won't react. It also redirects stdout/stderr to nohup.out (or a file you specify). POSIX-standard, portable to any shell.
disown intervenes after launch. It removes the process from the shell's job table so the shell won't notify it on exit — but the process has no built-in signal immunity. Some SSH/terminal implementations broadcast SIGHUP to the entire process group on disconnect, bypassing the shell entirely. In that case disown alone won't save you.
# nohup: know you need it upfront
nohup python train.py > train.log 2>&1 &
# disown: the "oh crap I need to leave" rescue
./long_task.sh # already running...
# Ctrl+Z to suspend, then:
bg
disown %1
# Belt and suspenders — use both
nohup cmd > out.log 2>&1 &
disown
The combination is the safest one-liner: nohup gives the process its own signal shield, disown cleans up the job table so closing the terminal is truly a no-op.
For anything long-lived (a server, a daemon), neither is the right tool — use systemd, supervisord, or tmux. nohup and disown are emergency measures, not service managers.
One gotcha with nohup: if you don't redirect output yourself, it writes to ./nohup.out, which can quietly grow to fill a disk. Always pair it with an explicit > log 2>&1.
When a Linux box slowly bleeds memory over hours, the kernel OOM killer kicks in too late — by then the machine is already frozen. Two complementary fixes: earlyoom kills a hog before the system locks up, and a periodic memory snapshot gives you post-mortem data next time it happens.
earlyoom
Install and go — on Debian it's one command and the service auto-enables:
sudo apt-get install -y earlyoom
systemctl status earlyoom.service
Defaults (Debian package): kills when available RAM drops below 10% and available swap drops below 10%. Sends SIGTERM first, then SIGKILL. Configurable via /etc/default/earlyoom or override flags in the systemd unit.
Memory snapshot every 5 minutes
When the machine eventually does die, you want to know what was growing. A systemd timer + shell script + logrotate gives you that with near-zero overhead.
The capture script (/usr/local/bin/memsnap-capture):
…more
You have a screen session running in one terminal and want to interact with it from a second terminal on the same host. Two modes:
Share it — both terminals see and type in the same session:
screen -x <session>
Great for pair debugging. Both clients are attached simultaneously.
Take it over — detach the other client and bring the session here:
screen -d -r <session>
Use this when you're switching from SSH to local, or reclaiming a session you accidentally left open elsewhere.
Find your session name first:
screen -ls
If the session belongs to a different user, you'll need that user's permissions (or sudo).