balena-cli ssh non-interactively into running service

I’m looking to ssh non-interactively into a service on my balenaOS host.

From SSH access - Balena Documentation

Note: To run a command in a non-interactive way, you can pipe commands to the CLI’s stdin. For example, echo "uptime; exit;" | balena ssh <device-uuid> .

This works well for running commands on the Host, but I can’t figure how to format it in such a way that my commands are piped into a running service. I tried piping to balena ssh <device-uuid> <service> but it doesn’t return anything. I also tried writing a testfile in the remote command but the file was not created.

$ echo "uptime; exit;" | balena ssh <device-uuid>
[debug] original argv0="balena" argv=[/usr/local/balena-cli/balena,/snapshot/versioned-source/bin/balena,ssh,<device-uuid>] length=4
[Debug]   Fetching application by name <device-uuid> (string)
[Debug]   Application not found
[Debug]   Fetching device by UUID <device-uuid> (string)
=============================================================
    Welcome to balenaOS
=============================================================
 16:37:07  up  17:17,  1 user,  load average: 0.33, 0.50, 0.50
$ echo "uptime; exit;" | balena ssh <device-uuid> <service>
[debug] original argv0="balena" argv=[/usr/local/balena-cli/balena,/snapshot/versioned-source/bin/balena,ssh,<device-uuid>,mariadb] length=5
[Debug]   Fetching application by name <device-uuid> (string)
[Debug]   Application not found
[Debug]   Fetching device by UUID <device-uuid> (string)

I tried adding --verbose and enabling DEBUG=1 but it didn’t return anything useful that I could find.

# environment
$ lsb_release -a
Distributor ID:	elementary
Description:	elementary OS 5.1.4 Hera
Release:	5.1.4
Codename:	hera

$ uname -a
Linux <hostname> 5.3.0-51-generic #44~18.04.2-Ubuntu SMP Thu Apr 23 14:27:18 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

$ balena -v
11.29.3

$ balena device <device-uuid>
== SILENT MOUNTAIN
ID:                 2006664
DEVICE TYPE:        raspberrypi3-64
STATUS:             idle
IS ONLINE:          true
IP ADDRESS:         192.168.8.9
APPLICATION NAME:   nextcloud
UUID:               <device-uuid>
COMMIT:             43865036494c0ed0073ea8e958823561e519f842
SUPERVISOR VERSION: 10.6.27
IS WEB ACCESSIBLE:  false
OS VERSION:         balenaOS 2.47.0+rev1
DASHBOARD URL:      https://dashboard.balena-cloud.com/devices/<device-uuid>/summary

Hi, I tested this successfully e.g. for a service named main. Perhaps ruling out the simplest explanation first, you have correctly specified the name of the running service, which would be determined from your docker-compose.yml file if a multi-container application or main if a single container?

$ echo "pwd; exit;" | balena ssh 192.168.1.111 main
/usr/src/app

Unfortunately my devices are in Production mode so I can’t access locally via IP as you did in your example.

I confirmed that the service name is valid for the device UUID I’m using. I’ve tried with various devices and various services with the same result.

Are you able to reproduce the test with a device in Production mode?

Yes, I can replicate this on a production device accessing the device over the VPN (due to specifying the device UUID). If, after adding an SSH key to config.json and attempt to access via IP I get a different error:

echo "pwd; exit;" | balena ssh 192.168.86.185 main
Could not access docker daemon on device 192.168.86.185.
Please ensure the device is in local mode.

This is unsupported, and there is an issue here https://github.com/balena-io/balena-cli/issues/1482 to fully support this. Perhaps you can try some of the workarounds listed in that issue.

I got my utility working and published my efforts so others can benefit :slight_smile:

Thanks for your help!

Great stuff, and glad you got it working! Let us know if you need any help!