[SOLVED] Unable to execute script on a remote host using ssh

  • Platform information:
    • Hardware: Raspberry Pi
    • openHAB version: 4.1.1

I’m made a rule to checking presence of different phones using a bash script.
This works for me local.
But if I try to call the script using ssh on the remote host it seems to be not executed.

!#/bin/bash
#1 phone1, 2 phone 2, 3 phone3 

case $1 in 
  1) MAC="xx:xx:xx:xx:xx:xx"  ;;
  2) MAC="xx:xx:xx:xx:xx:xx"  ;;
  3) MAC="xx:xx:xx:xx:xx:xx"  ;;
esac

if sdptool browse $MAC > /dev/null
  then 
     echo "ON"
  else
     echo "OFF"
fi

If I call this script local from the rule everything works fine
I transferred this script to the remote host and try to execute it from the terminal of the openhab server using this command

sshpass -p xxxxxxx ssh pi@192.168.1.11 /schripts/bt.sh 2

It also works fine.
But if I call the same command from the rule this skript seems not be executed.

When you call a script or command from a rule or the Exec binding, that script or command is running as user openhab. When you run it from the shell, that command is running as your login user. These have very different environments.

Furthermore, you don’t get a full shell when running these from openHAB. Is sshpass in openhab’s path? Is ssh in openhab’s path? Has openhab ever sshed to the machine? If not ssh is probably asking to accept the host key from 192.168.1.11 before continuing.

When using executeCommandLine always pass a Duration as the first argument and log out what the command returns. That will show you the actual results of the command which usually tells you what’s wrong. If using the Exec binding, link a String Item to the output Channel to get the same info.

How do you call it from within your rule ? Do you use executeCommandLine or the exec binding ?
In case you use the exec binding did you add the command to the whitelist ?
Is there any entry in the log file ?
The command consists of several parameters do you use the command in the right way - e.g. in case of executeCommandLine are the individual parameters separated by comma ?

Best would be to show more about the exact implementation.

You easily can run / check the command using openhab privileges by getting an openhab shell

sudo su -s /bin/bash openhab

Now try your call to sshpass again.

The calling user is openhab, but I call the remote script as user pi.

status = actions.Exec.executeCommandLine (time.Duration.ofSeconds(5),"sh", "-c", "sshpass -p xxxxxxx ssh pi@192.168.1.11 /schripts/bt.sh 2");
console.log (status);

That’s the call in execute.
There is nothing returned in the openhab console and I also get no error.
I tried to call this script also as openhab user to avoid excepting the key.
It also works form command line.

maybe consider to use another way to call the script.

  • setup a public/private key for user openhab (does not need to be created as user openhab). Don’t set a password for the private key.
  • paste the public key to /home/pi/.ssh/authorized_keys at 192.168.1.11
  • copy the private key to $OPENHAB_USERDATA/.ssh/
  • use command
status = actions.Exec.executeCommandLine(time.Duration.ofSeconds(5), "/bin/sh", "ssh", "pi@192.168.1.11", "-i <name-of-private-key>", "/schripts/bt.sh", "2")

where <name-of-private-key> is the file name or the complete path to your private key.
Maybe you will need to tweak some permissions,
$OPENHAB_USERDATA should be 755 (read and execute but not write for group members), .ssh has to be 700 afaik. .ssh and the private key should be property of user openhab.

Are you sure about path and name of the script? /schripts/ seems to be an odd path…

1 Like

Of course it was a typo.
Maybe it was by copy.
I granted the user pi on the remote host to root group so I didn’t have to enter the password.
I also tried the solution with the key.
But same.
I get no returvalue in the script.
If I call the command from terminal all works fine.
It seems that the command is not executed.

This is the file on the remote computer I´m calling

l#!/bin/bash

#1=Alex, 2=Clarissa, 3=Gottfried
case $1 in
   1) MAC="64:5d:f4:21:85:c8" ;;
   2) MAC="e0:98:7e:b9:5e:fc" ;;
   3) MAC="dc:6a:e7:1b:f1:5a" ;;
esac
touch /script/test.txt

if sdptool browse $MAC > /dev/null
   then
      echo "ON"
      echo "ON" > /scripts/test.txt
   else
      echo "OFF"
      echo "OFF" > /scripts/test.txt
fi

I added a touch to the script expecting a file with the result of execution.
But after starting the rule there was no file on the remote computer.
But I get no error in the log when calling the remote command.

Try

status = actions.Exec.executeCommandLine (time.Duration.ofSeconds(5),"sh", "-c", "sshpass -p xxxxxxx ssh pi@192.168.1.11 /schripts/bt.sh 2 2>&1");
console.log (status);

It doesn’t change anything.
It seems that the remote call is not executed.
But I also get no error in the by watching the log or in the returnsate.
I expected a file test.txt on the remote computer, but it is no file created.
If I call this command from the terminal I get a returnvalue and the file is also created.

I would try to put as many parameters as possible into a script. As far as I remember redirection ( > ) and pipes ( | ) are not supported by executeCommandLine.

So the script would look like:

#!/bin/sh -x
/usr/bin/date >> /tmp/test.txt
/usr/bin/sshpass -p xxxxxx /usr/bin/ssh -vvv pi@192.168.1.11 /scripts/bt.sh 2 > /tmp/result.txt 2>&1

-vvv will generate debug output for the ssh connection
STDOUT and STDERR output will be stored in /tmp/result.txt
if this script is started it will be logged in /tmp/test.txt

The call to executeCommandLine then would be be

status = actions.Exec.executeCommandLine (time.Duration.ofSeconds(5),"/path/to/script.sh");
console.log (status);

/path/to/script.sh of course need to be replaced with correct values.

It doesn’t work because executeCommandLine doesn’t run with a shell all that sort of stuff is handled by the shell. However, here you are starting up a shell (sh -c) so everything after that point should be operating in a shell and redirection and piping and such should work just fine.

But in general, you are correct. You have a lot more control over everything if all that sort of thing is put inside a script. Then you know that you are working in a shell, get to choose the shell in the first place, and you don’t need to fight with the way executeCommandLine manages arguments.

I got it to work.
I created for every person a seperate script file on the host and the remote computer.
So I could call the executeCommandLine without any parameters and the ssh command also without any parameters.

status = actions.Exec.executeCommandLine (time.Duration.ofSeconds(5),"/scripts/btremoteC.sh");
!/bin/sh
#btremoteC.sh
/usr/bin/sshpass -p xxxx /usr/bin/ssh pi@192.168.1.11 /scripts/btClarissa.sh

!/bin/bash
#btClarissa.sh
if sdptool browse "e0:98:7e:b9:5e:fc" > /dev/null
   then
      echo "ON"
   else
      echo "OFF"
fi

This is my way to check presence in different parts of the house.
Thank’s a lot to all.

1 Like