Command Scripting

In this section we make use of Deviceplane's features to write custom scripts to manage your devices however you decide!

We'll go over (in order of complexity):

  • Printing out the names of offline devices - Useful for piping to other commands
  • Running a command on multiple devices - And printing the output of each run in STDOUT
  • Running a full bash script on multiple devices - With a workflow for saving the output of each run to a separate file

After reading this page, you should know where to start if you want to run batch scripts to get the output of files on your devices, perform package upgrades or install kernel updates on your entire fleet, or simply create a local script to periodically log a list of offline devices, which you could show in your menu bar.


For ease of use, these examples use jq, a simple CLI utility for parsing JSON. It's available on most package managers and can also be downloaded as a binary.


Printing out the names all offline devices

To print out all information on devices, we can use the deviceplane device list command. Pass in a filter argument, --filter status=offline, and we can select only the offline devices. Output json with -o json and pipe into jq, then select the name attribute of each object.

Our final command is:

deviceplane device list --filter status=offline -o json | jq '.[] | .name'

And should list the names of all offline devices. Currently, there's only one device offline in our demo project, so our output looks like this:


Reading the output of a command on all devices

In order to read the output of a command run on a device, we'll have to SSH into the device, and run the command. However, we can't SSH into devices that are offline, so let's first grab the list of all devices that are online. We can use the same command as in the last section, just remember to filter status to be online instead of offline: deviceplane device list --filter status=online -o json | jq '.[] | .name'

We can pipe this into xargs -n1 -I {} echo "The device {} is online" to echo for each line of output we get, replacing {} with the contents of each line. Next, we'll replace echo with our ssh command.

Our ssh command will look like deviceplane ssh $DEVICE_NAME $COMMAND, for each device, substituting $COMMAND with the command that we want to run on the device. Let's say we need every device's bound IP addresses. We can use the hostname -i command to get the IP addresses, so our command will be deviceplane ssh $DEVICE_NAME hostname -i, and if we'd like, we can prefix it with an echo command to echo out the device name before printing the IPs.

Now, putting it all together, we get:

deviceplane device list --filter status=online -o json | jq '.[] | .name' | xargs -n1 -I {} deviceplane ssh {} "echo {}\'s IPs: && hostname -I"

Which gives us the output:

elegant-lamarr's IPs: 2601:645:8400:9760::dcff 2601:645:8400:9760:7ff2:b063:4c20:1bf9
condescending-jones's IPs: 2601:645:8400:9760::c13e 2601:645:8400:9760:c1a8:d7c3:2285:64a3
pedantic-mcnulty's IPs:
competent-bohr's IPs: 2601:645:8400:9760:4ddb:c01d:c7b9:f801 2601:645:8400:9760:9ed:313:6b5:739e 2601:645:8400:9760:20ce:500e:ef1c:b81 2601:645:8400:9760:114d:839f:c601:96eb 2601:645:8400:9760:11b3:1009:165:3f8d 2601:645:8400:9760:e90a:fa6:79f:5df6 2601:645:8400:9760:3dd1:e263:35d5:f8dd 2601:645:8400:9760:d4e3:4c1:5240:446d

Running a bash script on multiple devices

For more complicated workflows, just a single command isn't enough. You might want an entire script to be run, and its output saved separately for each device.

The following script takes in a second file, and runs it on all online devices, storing the output for each device in a separate text file:

set -e
# Get all devices, and split them into online and offline devices
# Note, doing it this way ensures that we don't have devices missing from a list. For example, if a device changes state between two queries, we might miss it in our list.
ALL_DEVICES=$(deviceplane device list -o json)
ONLINE_DEVICES=$(echo $ALL_DEVICES | jq -r '.[] | select(.status == "online") | .name')
OFFLINE_DEVICES=$(echo $ALL_DEVICES | jq -r '.[] | select(.status == "offline") | .name')
echo "Online Devices:" $ONLINE_DEVICES
echo "Offline Devices (will not run commands on):" $OFFLINE_DEVICES
total=$(($(echo "$ONLINE_DEVICES" | wc -l )))
echo "($i of $total) running on $DEVICE"
# Get our input file, and execute it on the device, then save that output into a file
echo "$(deviceplane ssh "$DEVICE" "$(cat $1)")" > "$DEVICE"_output.txt

So, if our second file were the following:

set -e
echo "My current host name is:"
echo "\n"
echo "My IPs are:"
hostname -i
echo "\n"
echo "Creating and deleting a new file:"
touch newfile.txt
rm newfile.txt

We could name our files and, and run the following (after chmod +x


Which would output the following:

Online Devices: elegant-lamarr condescending-jones pedantic-mcnulty competent-bohr
Offline Devices (will not run commands on): condescending-feynman
(1 of 4) running on elegant-lamarr
(2 of 4) running on condescending-jones
(3 of 4) running on pedantic-mcnulty
(4 of 4) running on competent-bohr

And leave the following files:

ls -l
total 48
-rwxr-xr-x 1 cyrusroshan staff 574 Jan 27 23:24
-rw-r--r-- 1 cyrusroshan staff 190 Jan 27 23:24
-rw-r--r-- 1 cyrusroshan staff 213 Jan 27 23:32 competent-bohr_output.txt
-rw-r--r-- 1 cyrusroshan staff 199 Jan 27 23:32 condescending-jones_output.txt
-rw-r--r-- 1 cyrusroshan staff 199 Jan 27 23:32 elegant-lamarr_output.txt
-rw-r--r-- 1 cyrusroshan staff 271 Jan 27 23:32 pedantic-mcnulty_output.txt

To look at the output for the device elegant-lamarr, read the file elegant-lamarr_output.txt to find:

My current host name is:
My IPs are:
Creating and deleting a new file: