How to solve Exec binding problems

One of the most common problems I help people with on this forum is dealing with the Exec binding. So I’m writing this post so I can reference it later.

Background

When openHAB is installed in the automated way (i.e. via apt-get) an openhab user is created and the service runs under that user. The openhab user has the following attributes:

  • no shell so one cannot log in or su to this user
  • limited rights
  • not a member of sudoers
  • has a home directory in /var/lib/openhab (or /var/lib/openhab2)
  • has no PATH environment variable beyond the system default

These are the usual sources of all Exec binding errors.

#The Exec Binding
The Exec Binding also has some of its own quirks.

  • it does not report success or failure of the command in the logs
  • it does not log the results of the command to the logs
  • sometimes for technical reasons it requires replacing spaces with @@

The above can also be a source of errors as well as limit your ability to diagnose and fix problems.

How to Debug

Some easy steps:

  • If the command or the called script calls sudo, make sure openhab is a member of sudoers and is configured with NOPASSWORD

  • Use the full path for all commands called by the binding and any commands called by any script called by the binding

  • Make sure the openhab user has permissions on all files that are called directly by the binding or called by a script that the binding calls.

  • Replace spaces with @@

If these steps do not work, we need to get some more information from the command, in particular we need to get the text that is generated when the command executes.

  1. Remove the exec binding config or link to the exec Channel (if using OH 2) from the Switch Item.

  2. Create a new rule that triggers when the Switch receives a command

  3. In this rule use val results = executeCommandLine(cmd, timeout) followed by logging out results.

val results = executeCommandLine("/bin/echo@@'The quick brown fox jumped over the lazy dog.'", 5000)
logInfo("execTest", results)

Only executeCommandLine that takes a timeout argument will wait for the command (up to timeout milliseconds) to finish and return any text generated by the script.

  1. Trigger the Switch and watch the logs for errors.

Common errors I’ve seen include:

  • Trying to ssh but the host is not part of the openhab user’s known hosts. Either copy the .ssh folder from your usual account to ~/openhab/.ssh (changing permissions and ownership of course) or run sudo -u openhab /usr/bin/ssh user@host and typing “yes” when ssh asks if you want to accept the ssh key.

  • Trying to ssh to a host without setting up certs for the openhab user. I really really recommend against trying to pass the password on the command line. Setting up an rsh keypair is so easy and once set up you never have to type in a password again. But if you neglect to generate a new keypair for the openhab user or copy your main keypair (the key files now become your password, protect accordingly) the openhab user will not be able to log into the remote host.

  • Incorrect permissions on the files in ~openhab/.ssh. ssh will not connect if the private key file is group or world readable.

  • Using sudo but failing to add the openhab user to sudoers with NOPASSWORD. If you are on the raspbian probably the easiest thing to do is run sudo visudo and copy what is there for the pi user and change “pi” to “openhab”.

  • “Command not found”, check your paths and permissions.

25 Likes

that’s really clear and helpful - thank you.

Great info, I am using the exec binding on openHAB2. Initially I was using the old way and that worked perfectly however, I updated openHAB2 and it broke everything. I know I could use the compatibility to continue with the old way but I really wanted to bite the bullet and set up the exec binding using channels. I did this and got it running, my script requires parameters to be parsed to it so I set up an exec thing:

Thing exec:command:tp-linkswitch [command="/etc/openhab2/scripts/tp-link.script
%2$s", autorun=true]

Then item
String RoomLiving “Light_Living” { channel=“exec:command:tp-linkswitch:input”}

Then sitemap
Switch item=RoomLiving label=“Living Room Lamp” icon=“light” mappings=[“
192.168.1.6 9999 on”=“ON”, “192.168.1.6 9999 off”=“OFF”

which works well sending the on or off command as required.

My issue is, if I want to send the command to switch the light on at dusk how can I address the light.
Do I have to create a run channel thus:

Switch RoomLivingSwitch “Light_Living” { channel=“exec:command:tp-linkswitch:run”}

and if so, how do I send it the parameters? I think I could just use sendCommandLine(“scriptname parameters”) but wasn’t sure if that was the best/correct way to do it?

2 Likes

Sadly the documentation for the 2.0 binding is not to the level it should be. And I’m running OH 2 in a Docker container so the Exec binding is pretty much useless to me.

I think the way it works is you would have three Items:

  1. an input Item which gets set to the command line arguments and mapped to the input channel
  2. an output Item which gets set to the result of the command and mapped to the output channel
  3. and a run Item which gets set to the run channel

So the order would be to postUpdate to the input Item, send the command to the run Item, then check for the result in the output Item.

Keep in mind the above is based off of a whole lot of assumptions, the description of the channels, and the examples at the end of the readme.

Thanks for the response Rich, I will try it out and let you know how it goes. I am hoping I can do it without reverting back to the “old way”.

I have to be honest, I am finding it hard to put this together as an elegant and maintainable configuration using the channel approach, it seems much easier to me to set up a dummy switch item and just use rules to fire the script using executeCommandLine - The problem I am having is that when the switch requires me to set up the parameters in the sitemap other things that I use with that switch either don’t work or work in a different way. For instance I can’t send that switch a simple ON command, it just does nothing. I also use a script that looks at the plug to see if it’s been changed from another device (Alexa) and updates the sitemap to show me that the light is on or off. When I do this with the channel the postUpdate actually changes the state of the plug whereas if it’s a simple representation of the switch it will just “display” the status and not change it.

I think I am going to go with

Item
Switch Living_Room "Living Room Lamp" ["Switchable"]

Rule
rule "Turn the light on"
when
     Item Living_Room received command ON
then
    executeCommandLine("/etc/openhab2/scripts/Switch.script 192.168.1.4 9999 on")
end

and a similar one for off and each switch. - It works, and it’s robust and easy to read.

PS the [“Switchable”] is so that Alexa can see it using the Hue Emulation

I am interested in your thoughts.

3 Likes

My main suggestion is to do what makes the most sense to you.

For the most part I’m ambivalent about the exec binding over all. It is the source of the most problems reported on this forum and I spend an inordinate amount of time helping people with problems with it. So I’m not the biggest fan of the binding in general (not that my complaints are really the binding’s fault).

Couple that with the fact that I can’t really use it because I run in a Docker container which makes it difficult for me to test things out on my own.

I’m not sure I 100% follow what you did here. Are you describing a case where you have one Switch mapped to several different channels or bindings? And which of the Exec channels did you include in this switch?

I think one of the challenges is how it splits everything up.

The run channel appears to represent whether or not the script is actually running and hopefully provide a way to actually trigger the script to run. But that only tells you that the script is running, not the result. You need to look to the output channel` to get at the result. I think this makes it difficult if not impossible to combine it with other Items where sending a command to that Item triggers the script and the result of the script populates the Item.

So using a proxy Item like this might be the only way to do that. However, you can still set up a Switch on the run channel and sendCommand(ON) to that Swtich instead of using executeCommandLine. Then you can combine your Items with the input channel which needs to represent the state of the device.

I think there needs to be a way to manage all three channels that you need as an entity it becomes confusing very quickly when you have more than one switch. I tried having a run channel and input channel and output channel but I just couldn’t get it to work the way I wanted to. I will keep an eye on the binding to see if it becomes easier to use for a script that operates a switch but until then I am going to rely on the rules to trigger the switch and let my scripts update the state so I can reliably know if something external has operated the switch.

The new Exec binding matches the the OH 2 way of doing things. Each “device” has multiple control points or outputs and each gets its own channel. So I wouldn’t hold my breadth on this changing in the future.

Gotcha, there’s more than one way to skin a cat so I will do as you advised and go with what makes sense to me.
On another note, do you know of anything that can manage the proliferation of things/items/scripts/rules/sitemaps?
I am thinking of putting a spreadsheet of some kind together, I often find myself having jump back and forth from items, scripts etc to keep all the names in order. I am not sure if there is anything out there that can do that for you?

Designer.

You can start to type the name and hit <ctrl><space> and it will tell you all the valid completions. It also has a pane in the lower left corner that lists all your Items. And if you happen to mistype an Item name, it will highlight it as an error (as well as any other syntax error you might introduce). And it does this for ALL the config files including .cfg, .sitemap, .items, .things, .rules, etc.

You really should be using Designer.

Beyond that, it is useful to come up with a standardized and formulaic naming convention so you can pretty reliably guess at the name of an Item. Break your Items and Rules up into separate files for additional manageability. I group everything by function (.e.g lighting, presence, etc). 90-100% of all the Items that my lights.rules file use are defined in lights.items. That helps a lot as well.

I have been breaking them up by function and do have a lot of smaller files as a result. That makes it much better for readability and coming back to it when it breaks ;-/

I do use a nomenclature that works for me and allows me to guess, that’s how I am working now. I was just looking for a better way to organize.

I have tried designer but most of the time when I am making changes I am remote from the openhab machine with only ssh access so I am not sure designer is going to be great for me unless I edit everything locally and upload it afterward.

I will look at ways I can use designer. I do like the syntax checking that it provides.

Personally I run VNC on a machine back home that also has Designer. Then I ssh tunnel the VNC client from where ever I am. It is nice and safe and it lets me use Designer where ever I may be.

If your OH machine is headless, you might need to set up a samba share or nfs share to allow the machine that does have a graphical environment can access the config folder.

Another approach is to use scm (e.g. git, svn, mercurial, github) to push/pull your changes. It isn’t quite as clean as editing the files locally but it comes with the added bonus of keeping track of changes and giving you a backup.

Thanks for the input, I could run VNC on my server, it’s an Ubuntu box, but I do like the svn idea, that could work out well as it would kill two birds with one stone. Then I could just run locally and avoid any lag and just load the files into svn (or similar). I am already rsync’ing the files for a backup so it would achieve that too. - I will ponder the configuration and see what works.

Just for completeness, I use a git server called Gogs running in a Docker container. It’s super light weight yet gives you a web interface along the lines of Github which is nice.

SVN would certainly be easier than git to use, but it seems the world has gone to git these days so I bit the bullet and used it so every time I needed to interact with github I wouldn’t have to relearn how it works.

Good thought… I will look at it. I have committed to this home automation thing and want to make sure that whenever something breaks I can recover, I have had a couple of issues with network outages (changing IP addresses of stuff) and updates blowing away the way I was doing things (exec binding), I also need to setup the addons.cfg so I automatically get all my bindings back too.

I am finding myself a little reluctant to have everything in a database. I like having the files in the filesystem to edit. I am not sure if the way forward is completely database oriented or if there will always be a choice.

Well, last week (was it really only last week, maybe a couple of weeks ago) an update to OH changed from using MapDB to JSONDB. The great thing about that is that now the DB is a human readable and editable text file. So should something become corrupt you can go in and undo the damage. It also lets you more easily SCM control the DB to track changes and such.

That makes going the UI route a lot less risky for those who like to have text files for this sort of thing.

That being said, I pretty much only have automatically discovered Things in my DB. Everything else, including which add-ons are installed and core OH parameters are in config files. So in a worse case scenario all I have to do is blow away my userdata folder and I’ve a brand new install and the only thing I need to update are the automatically discovered Things.

More and more of OH 2 will move towards the UI being the “primary recommended approach” but I doubt the text based configuration will ever go away completely. Too many OH 1.x old timers would revolt if that option were taken away. :slight_smile:

Thanks very much for this tutorial @rlkoshak ! it helped very much in fixing some problems with ssh execution.

Nevertheless I am completely stuck with reading the current poewer delivered by my photovoltaics. The values from the inverters can be retrieved from a sqlite3 database which is located on anoher rpi (called pi1-pv). I am calling a bash-script on that rpi via ssh. I generetaed rsa keypair for user openhab and ssh-copied it to pi1-pv. Calling
sudo -u openhab /usr/bin/ssh -i /var/lib/openhab2/.ssh/id_rsa fre@pi1-pv /home/fre/scripts/pdc.sh 2100123456
works very fine. But all the following items do not work, though I followed your recommendation:

String inv1	"Inverter 1 [%s]"	<solarplant>	{exec="<[/usr/bin/ssh@@-i@@/var/lib/openhab2/.ssh/id_rsa@@fre@pi1-pv@@/home/fre/scripts/pdc.sh@@2100123456:60000:REGEX((.*?))]"}
String inv2	"Inverter 2 [%s]"	<solarplant>	{exec="<[/etc/openhab2/scripts/getpdc.sh:60000:REGEX((.*?))]"}
String inv3	"Inverter 3 [%s]"	<solarplant>	{exec="<[/tmp/pr100.py:60000:REGEX((.*?))]"}
String inv4	"Inverter 4 [%s]"	<solarplant>	{exec="<[/etc/openhab2/scripts/getpystr.sh:60000:REGEX((.*?))]"}

executing the above from within a rule via execCommandLine and logInfo (as you described above) is working fine!
BTW: pr100.py is simply:

#!/usr/bin/python
print 100

And getpystr.sh is just calling pr100.sh.

I set up a thing in the old way and this also works fine.

Thing exec:command:getpdc [command="/usr/bin/ssh -i /var/lib/openhab2/.ssh/id_rsa fre@pi1-pv /home/fre/scripts/pdc.sh 2100123456", interval=15, timeout=5]

String inv5 "[%s]"	{channel="exec:command:getpdc:output"} 

What am I doing wrong with my items?

I can’t say. I pretty much exclusively use executeCommandLine to call scripts so I have more control over when they get executed and can get more debug information. All I can recommend is to either use the Exec 2.x version which seems to work fine for you or stick with executeCommandLine which also works fine.

1 Like

I am on Exec binding 2.1.0-SNAPSHOT respectively on 2.0.0 on my test machine. Both react in the same way.

I though I might have problem with the REGEX expression, but the problem ist that exec within an item does definitely execute nothing. Even not en echo to a file in the tmp folder which has 777 rights.

String inv4 "Inverter 4 [%s]"	<solarplant>	{exec="<[/bin/echo@@4711:10000:REGEX((.*?))]"}

also does not work.

Alright, I’ll give it up and will use things and items