Script connect via ssh and run command

Hi,
I am trying to connect from my openhab instance to another server via ssh and execute a command via script.

  • via openhab cli I can connect to the server with

ssh user@ip

  • the auth is done with ssh key, so there is no need to enter a password
  • sudo can be executed without a password

I created a new rule, as action I selected inline script rule dsl and used:

executeCommandLine(Duration.ofSeconds (1),“ssh user@ip”, “sudo systemctl stop myservice“)

But I just get

WARN org.openhab.core.io.net.exec.ExecUtil Failed to execute commandLine

Thanks for your help!

BR Dirk

Thanks, but I already read it twice and I am still not able to get the correct syntax.
Otherwise I wouldn’t have opened this thread.

One additional relevant piece of information that isn’t in the post @jimtng linked to (please read it because it is relevant overall) is that when you call executeCommandLine, the command is running as the same user that openHAB runs as, which is usually openhab. That is almost never the same user that you are logged in as so “via openhab cli I can connect to the server with” is almost irrelevant. The ssh key you’ve set up is unknown by the openhab user and you need to set up that user with the ssh keys and permissions and everything else it needs to run the command.

Try this

executeCommandLine(Duration.ofSeconds (1),“ssh", "user@ip”, “sudo systemctl stop myservice“)

If that doesn’t work, break up the last argument

Still no luck, tried it with this:

executeCommandLine(Duration.ofSeconds (1),“ssh", “dirk@192.168.178.180”, “sudo”, “systemctl”, “stop”, " myservice“)

and this:

executeCommandLine(Duration.ofSeconds (1),“ssh", “dirk@192.168.178.180”, “sudo”, "systemctl stop myservice“)

And getting

22:54:43.321 ERROR org.openhab.core.automation.module.script.internal.handler.AbstractScriptModuleHandler Script execution of rule with UID ‘-service-restart’ failed: executeCommandLine(Duration.ofSeconds (1),“ssh", “dirk@192.168.178.180”, “sudo”, “systemctl”, “stop”, " myservice“)

and this

22:52:28.419 ERROR org.openhab.core.automation.module.script.internal.handler.AbstractScriptModuleHandler Script execution of rule with UID ‘-service-restart’ failed: executeCommandLine(Duration.ofSeconds (1),“ssh", “dirk@192.168.178.180”, “sudo”, "systemctl stop myservice“)

Ok, but for my understanding please explain.
I connect with user eg dirk to my other server via ssh from openhab console.
So why is there the user openhab involved?

The ssh key was created for user eg dirk. Why is openhab user important when the command get executed under another user on another server?
Thanks!

Because you are running the command as user openhab and the user you pass on the command line to ssh is the user on the other machine, not the local machine.

User openhab needs to have the ssh key.

Here’s an experiment you can run. On the command line:

sudo -u openhab
ssh dirk@192.168.178.180 ls

The first line gives you a command line running as the openhab user, same as what executeCommandLine gets.

You’ll get either a password prompt or a cert error depending on how the ssh server is configured when you run the second command.

Luckily to get that second line to work is probably as simple as copying the ssh public and private keys to ~openhab/.ssh which is going to resolve to /var/lib/openhab/.ssh. This directory does not already exist though, you’ll have to create it. And the cert files must be owned by user openhab and have read permissions for only the openhab user.

Once you can execute the command as user openhab on the command line, use the version of the call to executeCommandLine @jimtng posted above in post 5.

Are you running openhab in a docker? We need to know a bit more detail about your openhab setup (os etc)

Sorry, I am on

openHAB 4.3.2 - Release Build
Release = Raspbian GNU/Linux 11 (bullseye)
Kernel = Linux 6.1.21-v8+

Tried to do the experiment. The first line didn‘t work I guess.

This is what I get:

openhabian@openhabian:~ $ sudo -u openhab
usage: sudo -h | -K | -k | -V
usage: sudo -v [-AknS] [-g group] [-h host] [-p prompt] [-u user]
usage: sudo -l [-AknS] [-g group] [-h host] [-p prompt] [-U user] [-u user] [command]
usage: sudo [-AbEHknPS] [-r role] [-t type] [-C num] [-D directory] [-g group] [-h host] [-p prompt] [-R directory] [-T timeout] [-u user] [VAR=value]
[-i|-s] []
usage: sudo -e [-AknS] [-r role] [-t type] [-C num] [-D directory] [-g group] [-h host] [-p prompt] [-R directory] [-T timeout] [-u user] file …
openhabian@openhabian:~ $

Edit:
ok i was able to get it working. This is what I’ve done:

sudo -u openhab ssh-keygen
sudo -u openhab ssh-copy-id dirk@192.168.178.180

Now I can connect with this:

sudo -u openhab ssh dirk@192.168.178.180

Next I will try to run the command via executeCommandLine

Got it working!

Thank you to @jimtng & @rlkoshak .

executeCommandLine(Duration.ofSeconds (1),“ssh”, “dirk@192.168.178.180”, “sudo”, “systemctl”, “stop”, “myservice”)

Hi guys,

I am running in Docker. Where do I mount my keys-folder?

Further things I’ve done are: create a persistent folder called ‘conf-init.d’. Have that mount to /etc/cont-init.d and put a script inside with

#!/bin/bash -ex

sed -i \
    "s/\#org.apache.karaf.shell:sshHost\s*=.*/org.apache.karaf.shell:sshHost=0.0.0.0/g" \
    "${OPENHAB_CONF}/services/runtime.cfg"

All according to some posts in this forum. The script came from this page. This to setup a ssh server when the container is started.

Anything I missed?

Thanks!

Yes,

you shouldn’t do this. Instead, edit conf/services/runtime.cfg and enter:

org.apache.karaf.shell:sshHost=0.0.0.0

Note the warning: This opens up your openhab to accept connections from anywhere that your network firewall allows.

Thanks for your reply @jimtng.

Somehow, this already seems to be the case:

################ MISCELLANOUS ###################

# The karaf sshHost parameter configures the bind address for the ssh login to karaf.
# Default is 127.0.0.1 (localhost), so it is only possible to login from the local machine.
#
# Setting this to the address of another network interfaces will allow login from this network.
# Setting this to 0.0.0.0 will allow login from all network interfaces.
#
# !!! Security warning !!!
# Remember to change default login/password, if you allow external login.
# See https://www.openhab.org/docs/administration/console.html for details.
#

org.apache.karaf.shell:sshHost=0.0.0.0

When I open the terminal in Docker, I am able to send eg. ping commands but ssh can’t be run. It says: bash: ssh: command not found. I’ve come to the discovery that the cont-init.d folder also doesn’t mount. Set all permissions and users correct though…

If that’s already the case then your script doesn’t do anything and I’d suggest removing it.

You do need to mount that cont-init.d in your docker so openhab can see it.

Then add this script in there to install ssh

#!/bin/sh

apt-get -qq update
dpkg --configure -a
apt-get -qq install -y openssh-client

But I’m confused, sorry I haven’t re-read everything back and I’ve forgotten from before.

Do you need to connect TO your openhab (in docker) or do you need to connect to another host FROM openhab?

If it’s the latter, you don’t need to set your sshHost to 0.0.0.0 - that’s just unnecessarily exposing it to the network.

It’s the latter. So from OH towards another, in this case, Raspberry Pi. I will comment this back out again. Thanks for the heads up.

In the meantime, the dir did mount and your script works like a treat! I can now go into the Docker container, open the terminal and ssh into the other Pi. For the passwordless setup, we need the certificate(s). I generated this before, or at least tried to, so I wonder where to mount this folder in the container? Do I need to touch ~/.ssh and place it there or is there some other place to stick it?

Yeah I mounted mine like this in docker-compose

      - /home/openhab/.ssh:/openhab/.ssh

Hm, from the terminal all works fine, when I put it in a bash script, all works fine but when I put is directly in the Rules as

var test = actions.Exec.executeCommandLine(time.Duration.ofSeconds(10), "ssh", "pi@192.168.xx.xx")
console.log(test)

it comes back with the Failed to execute commandLine '[ssh pi@192.168.xx.xx]'-error. Ideally I keep the code in one place (so avoid setting up bash scripts). Are there any more hint as to why this approach doesn’t work?

I added all commands, with and without quotes to the exec.whitelist file…

Don’t know what happened but after yet another restart of the container it works!

I now just get a warning bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8) in my console.log(test) as return but at least after that also the expected output! Need a way to filter this out but that is beyond the scope of this topic.

Thanks for the help @jimtng !