cl-remote: параллельное выполнение команд на рабочих станциях
Updated 9 November 2026
cl-remote is an administration utility: it runs commands and ready-made service scripts on many machines in parallel over SSH. The utility first finds active addresses on the network by an open port, then connects to each responding machine and displays the results in a single table. This page is intended for administrators who maintain a fleet of Calculate Linux workstations.
This page applies to cl-remote 0.3.2.
Purpose
It is needed when a single action must be performed on dozens of machines at once: check build versions, identify which workstation an employee is using, send notifications to desktops, prepare an update from an image. Compared with manually going from machine to machine over ssh, cl-remote provides:
- no agent on the machines: everything runs over ssh using the target system's standard tools, and scripts do not remain on the machine after the job;
- fast filtering of unavailable addresses: port checks run in parallel and take no longer than the SCAN_TIMEOUT for the whole segment, so powered-off machines do not delay the sweep;
- parallel execution with a controllable degree of parallelism — the -j parameter;
- selection by logged-in users: run an action where someone is working, or, conversely, only where no one is and a reboot is safe;
- networks are described once in the configuration file — afterwards they are referenced by name rather than by an address list;
- a ready-made set of scripts for fleet maintenance: system versions, users, interface speeds, notifications, updating from an image, access point setup.
At the same time, the utility remains a simple shell tool: one invocation produces one table with a result for each machine.
Installation
The utility is installed from the Calculate repository as the app-admin/cl-remote package:
emerge -a cl-remote
Settings are read from the /etc/calculate/remote.env file — right after installation, copy the sample /etc/calculate/remote.env.example to this path and uncomment the required lines. Without the settings file, the utility does not work.
cp /etc/calculate/remote.env.example /etc/calculate/remote.env
SSH Connection
cl-remote invokes ssh without specifying a login, so the ssh client selects the account on the target machine. Any user can run the utility itself on the administrator's machine — what matters is that system-level actions on the target machine run as root. To do this, run cl-remote as root or specify the User root directive in the client's ~/.ssh/config. In both cases, set up passwordless login to root: generate a key pair (ssh-keygen -t ed25519), add the public key to the root account of the machines (ssh-copy-id root@<address>), and specify the private key path in the SSH_KEY variable.
If key-based login is not set up, run it with the --ask-pass parameter: the utility requests the SSH password once and uses it to authenticate all connections through sshpass. Without --ask-pass, only key-based login works: a machine that does not accept the key is considered unavailable — the utility issues no further prompts.
Ключи серверов не проверяются
Connections are made without verifying the target machine's public key and without writing to known_hosts. The utility assumes that the administrator trusts the addresses listed in your configuration.
Configuration
cl-remote discovers machines by port: from the entire address list it connects to those with the probe port open. By default this is 22 — suitable when sshd runs on every machine of the fleet. To distinguish your machines from the rest of the network equipment, mark them with an additional port: configure sshd to accept connections on it as well, and specify the number in NET_PORT. Sweeping a segment of 254 addresses takes less than a second, so discovery results do not need caching — each run finds the machines anew.
Address lists and network names are stored in the configuration file: NET_ADDR holds "name — address range" pairs, NET_NAME holds "name — description" pairs (displayed by cl-remote -t list), and the NET variable sets the default network: without the -t parameter, it is this network that is used. NET_PORT is set in the probe[:ssh] format: the first port is for discovery, the second (when omitted, the shared SSH_PORT) is for connecting.
Example of a configured file:
/etc/calculate/remote.env
# Default network for cl-remote NET="labnet" # Network names: the name — description pair is shown by cl-remote -t list NET_NAME=( labnet "Lab network" officens "Office network" ) # Network address ranges: the name — address list pair NET_ADDR=( labnet "pc1 pc2 pc3" officens "192.168.1.{10..20}" ) # Network ports in the probe[:ssh] format NET_PORT=( labnet "22" ) # Number of simultaneous connections JOBS=10 # Private key for passwordless login SSH_KEY="/root/.ssh/id_ed25519"
The list query displays the registered networks and the default network:
Network: [labnet] Lab network [officens] Office network Default network: labnet # The default value can be overridden in 'remote.env'.
Targets
A target is set as a network name from the configuration, an IP address, a hostname, or a brace-expanded range; the -t parameter may be repeated several times. The command can also be sent to an entire segment — it reaches only the machines that respond, and the sweep time is shown in the last table row:
HOSTNAME IP OUTPUT
--------------------------------------------------------------------------------
pc1 192.168.1.11 ivan pts/0 2026-11-09 14:10 (192.168.64.5)
petr pts/1 2026-11-09 14:40 (192.168.64.6)
root tty1 2026-11-09 13:40
pc2 192.168.1.12 ivan pts/0 2026-11-09 14:10 (192.168.64.5)
petr pts/1 2026-11-09 14:40 (192.168.64.6)
root tty1 2026-11-09 13:40
pc3 192.168.1.13 ivan pts/0 2026-11-09 14:10 (192.168.64.5)
petr pts/1 2026-11-09 14:40 (192.168.64.6)
root tty1 2026-11-09 13:40
Total: 3 Success: 3
Execution time: 0.0 sec.
The examples use the administrator's lab subnet 192.168.1.0/24: machines pc1—pc3 answer at 192.168.1.11—192.168.1.13; substitute your own working addresses.
Extra addresses are removed from the selection with the -x parameter. Exclude an address in the same form in which it entered the target: ranges as numbers, networks as names:
HOSTNAME IP OUTPUT
--------------------------------------------------------------------------------
pc1 192.168.1.11 ivan pts/0 2026-11-09 14:10 (192.168.64.5)
petr pts/1 2026-11-09 14:40 (192.168.64.6)
root tty1 2026-11-09 13:40
pc3 192.168.1.13 ivan pts/0 2026-11-09 14:10 (192.168.64.5)
petr pts/1 2026-11-09 14:40 (192.168.64.6)
root tty1 2026-11-09 13:40
Total: 2 Success: 2
Execution time: 0.0 sec.
If no command is specified, the utility limits itself to a port check — this is how you determine which addresses in a segment are responsive:
HOSTNAME IP OUTPUT -------------------------------------------------------------------------------- pc3 192.168.1.13 Port 22 is open. pc1 192.168.1.11 Port 22 is open. pc2 192.168.1.12 Port 22 is open. Total: 3 Execution time: 0.0 sec.
Selecting Machines by Logged-In Users
The -u parameter filters machines by login status before the command runs: ON — only machines where someone is working; OFF — only machines where no one is logged in (safe for reboots); a login — only machines where the specified user is logged in; ALL (the default value) — no filter. This is how, for example, machines with an open root console are found:
HOSTNAME IP OUTPUT
--------------------------------------------------------------------------------
pc3 192.168.1.13 ivan pts/0 2026-11-09 14:10 (192.168.64.5)
petr pts/1 2026-11-09 14:40 (192.168.64.6)
root tty1 2026-11-09 13:40
pc1 192.168.1.11 ivan pts/0 2026-11-09 14:10 (192.168.64.5)
petr pts/1 2026-11-09 14:40 (192.168.64.6)
root tty1 2026-11-09 13:40
pc2 192.168.1.12 ivan pts/0 2026-11-09 14:10 (192.168.64.5)
petr pts/1 2026-11-09 14:40 (192.168.64.6)
root tty1 2026-11-09 13:40
Total: 3 Success: 3
Execution time: 0.1 sec.
A machine that fails the filter is omitted from the output: running with a login that no one has used yields an empty table:
HOSTNAME IP OUTPUT -------------------------------------------------------------------------------- Execution time: 0.0 sec.
Ready-Made Scripts
The -s parameter runs a script from the /usr/libexec/cl-remote directory: the script is transferred to the machine in full, where its run() function runs; arguments after the script name become its parameters. The list argument shows the scripts themselves, their descriptions, and invocation examples:
System Scripts:
[aproaming] Configuring OpenWrt access points with seamless Wi-Fi
roaming support (802.11r/k/v).
Example: cl-remote -t ap0812 -p 51022 -s aproaming
[rename-iface] Renaming the default network interface.
Udev in the initramfs assigns unique names to network
interfaces, which can be inconvenient to work with. This
script allows you to rename a network interface.
Warning: It's not recommended to use the name eth0 if
you have multiple network interfaces, as proper renaming
via systemd-udevd has been removed.
Example: 'cl-remote -s rename-iface lan0'
[users] Display system users
[version] Displaying the installed system version.
This script retrieves the installed version of
Calculate Linux. If an argument is provided, it compares
the version with the given value.
Example: 'cl-remote -s version 20250311'
[upgrade] Updating Calculate Linux from a system image without
modifying the existing installation
Example: 'cl-remote -j3 -s upgrade'
[notify] Sending Notifications to Users
Example: cl-remote -s notify "System Update" Reboot in
10 minutes!
[netspeed] Network Interface Speed
Displays the name and speed of the network interface.
If the speed does not match the maximum, an error is
displayed. Takes bridges into account.
Example: 'cl-remote -s netspeed'
User Scripts:
[kernel] Show the running kernel version
Measured on the target machine; the output is the
kernel version string
Example: 'cl-remote -s kernel'
Checking the System Version (version)
The script reads the build number from /var/lib/calculate/calculate.env; if you pass it a reference number, machines that differ are marked with a warning:
HOSTNAME IP OUTPUT -------------------------------------------------------------------------------- pc3 192.168.1.13 20261030 pc2 192.168.1.12 20261030 pc1 192.168.1.11 20261030 Total: 3 Warnings: 3 Execution time: 0.0 sec.
The machines have not yet updated to the latest release 20261106: the builds differ from the expected one, and the summary counted those rows as warnings.
Machine Users (users)
The script shows the logged-in users — the full name from the account and the primary group; a root login is marked with a warning:
HOSTNAME IP OUTPUT
----------------------------------------------------------------------
Name Group
pc1 192.168.1.11 Ivan Petrov users
Petr Sidorov users
root root
Total: 1 Warnings: 1
Execution time: 0.0 sec.
Desktop Notifications (notify)
The script finds users with an open graphical session and sends each one a notify-send notification; the first argument is the title, the rest is the notification text. The display time and icon are set by the NOTIFY_TIME and NOTIFY_ICON variables in /etc/calculate/remote-client.env.
Network Interface Speed (netspeed)
The script shows the interface of the default route and its current speed; when ethtool is available, it compares the current speed with the maximum supported one and marks the machines running below their limit with a warning. Bridges are taken into account: the physical interface under the bridge is displayed.
Upgrade from an Image (upgrade)
The script runs the upgrade-from-image preparation (cl-install -Uf) and reboots the machine only when no user is active on it. This is a heavy operation, so concurrent runs are limited — as in the example from the list itself: cl-remote -j3 -s upgrade.
Interface Name Unification (rename-iface)
Udev in initramfs assigns interfaces names based on their hardware position (enp19s0 and the like), so the names differ from machine to machine. The script brings local interface names to a form common across the fleet: the interface carrying the default route is renamed to the name passed as an argument (or to the value of RENAME_IFACE), and on every machine it then has the same name — for example, lan0. Besides the rename, the script edits /etc/conf.d/net and the runlevel script symlinks, and writes a rule into /etc/udev/rules.d/70-persistent-net.rules that binds the name to the MAC address, so the name survives a reboot. On machines with several interfaces, avoid choosing eth0 as the standard name.
Access Point Setup (aproaming)
The script prepares an OpenWrt access point for seamless 802.11r/k/v roaming. The network names of both bands, the Wi-Fi password, the regulatory domain, the channel width, NTP and the time zone are set by variables prefixed with AP_ in /etc/calculate/remote-client.env; if the Wi-Fi password is missing, the utility asks for it at startup.
Custom Scripts
A custom script is an ordinary shell file. The main part of the code runs in the run() function, which receives the arguments specified after the script name; the optional prepare() function runs on the administrator's machine before distribution and can, for example, set the heading of an extra table column — the CLIENT_TABLE_HEADER variable serves this purpose. Description lines starting with ## appear in the cl-remote -s list output. Custom scripts are searched for first in the user directory — by default /var/calculate/remote-scripts, and its path is overridden by the USER_SCRIPTS_DIR variable in /etc/calculate/remote.env; the script is then searched for among the system ones in /usr/libexec/cl-remote. The ready-made scripts from this directory can serve as a basis for writing your own. Values from /etc/calculate/remote-client.env and whatever prepare() has collected are delivered to the target machine together with the script; no trace of the script remains on the machine.
Example of a script that prints the kernel version:
/var/calculate/remote-scripts/kernel
## Show the running kernel version ## Measured on the target machine; the output is the kernel version string ## Example: 'cl-remote -s kernel' run() { uname -r }
Running a custom script on a machine:
HOSTNAME IP OUTPUT -------------------------------------------------------------------------------- pc1 192.168.1.11 6.18.57-calculate Total: 1 Success: 1 Execution time: 0.0 sec.
Displaying Results
Each processed machine becomes a table row with the HOSTNAME, IP and OUTPUT columns; multi-line command output is aligned to the third column. Rows are colored by outcome: green for success, yellow for a warning, red for an error; a ready-made script marks its result as a warning with exit code 73. Rows appear in the order results arrive, not alphabetically. The summary counters and the execution time are printed at the end.
The level filter -r keeps in the output only the rows of the requested level:
HOSTNAME IP OUTPUT -------------------------------------------------------------------------------- Execution time: 0.0 sec.
The --nocolor option disables colors (the utility does this automatically when output is redirected to a file).
Options
| Option | Value | Action |
|---|---|---|
--ask-pass |
— | Prompt for the SSH password and authenticate via sshpass |
-x, --exclude |
network / address / name | Exclude from the selection; repeatable |
-h, --help |
— | Show help |
-j, --jobs |
number (10) | Number of simultaneous connections |
--nocolor |
— | Disable colored output |
-p, --probe-port |
port (22) | Port for checking host availability |
-P, --ssh-port |
port (22) | SSH connection port |
-r, --report |
all / success / warning / error | Keep only rows of this level in the output |
-s, --script |
name or list | Run a ready-made script; list displays the script list |
-t, --target |
network / address / name | Set the target; repeatable |
-u, --using |
ALL / ON / OFF / login | Run, taking logged-in users into account |
The full list with examples is in the cl-remote --help output.
Configuration Variables
Values are set in /etc/calculate/remote.env (except the variables for ready-made scripts, which are stored in /etc/calculate/remote-client.env).
| Variable | Default | Purpose |
|---|---|---|
EXEC_TIMEOUT |
1200 | Time limit for command execution on the host, seconds |
JOBS |
10 | Number of simultaneous connections |
NET |
— | Default network for a run without -t |
NET_ADDR |
— | Pairs of "network name — address list" |
NET_NAME |
— | Pairs of "network name — description" for -t list |
NET_PORT |
— | Pairs of "network name — probe[:ssh]" |
PROBE_PORT |
22 | Port for checking host availability |
SCAN_TIMEOUT |
1.5 | Port check timeout, seconds |
SSH_KEY |
— | Path to the private SSH key |
SSH_PORT |
22 | SSH connection port |
USING |
ALL | Default filter by logged-in users |
USER_SCRIPTS_DIR |
/var/calculate/remote-scripts | Directory for custom scripts |
Source repository and additional examples: git.calculate-linux.org/calculate/cl-remote
Other administration guides are on the Working with Calculate page.