Catching output of ssh command via io.popen...coming up empty...

I’m playing with making a virtual switch for an mFi outlet. I’ve used dropbear to create the Vera private key for this, and have put the public end where it belongs on the mFi switch. If I give the command:

ssh -y -i /root/.ssh/mfi_rsa admin@192.168.1.137 cat /proc/power/relay1

When I am SSH’ed into Vera, I get back what I expect: 1.

When I use the same command via io.popen in Lua test code, the io.popen appears to succeed, but I get bumpkis back reading on the pipe:

local handle = io.popen("ssh -y -i /root/.ssh/mfi_rsa admin@192.168.1.137 cat /proc/power/relay1") local rlm_prowl_url if (handle) then local s = handle:read("*a") local status = s:gsub("%s+","") rlm_prowl_url = "https://prowl.weks.net/publicapi/add?apikey=" .. "..." .. "&application=Vera&event=mFi&description=Status+was[" .. status .. "]&priority=-1" else rlm_prowl_url = "https://prowl.weks.net/publicapi/add?apikey=" .. "..." .. "&application=Vera&event=mFi&description=SSH+FAIL" .. "&priority=-1" end luup.inet.wget(rlm_prowl_url)

I always get the “Status was []” result. Am I doing something obvious wrongly here?

–Richard

Are you sure that your use of :read and :gsub are correct? That seems to be a difference in that your second piece of code is using them and your first is not.

I am a iopopen newbie, but the code looks like examples I’ve seen elsewhere in the fora. Originally was trying to use os.execute(), but there’s no great way to capture the output for that, unless you direct it to a file, and then read the file. For something that is going to happen pretty frequently, that seemed dim.

The :read looks like every example I’ve seen, and is basically a slurp to end. The “:gsub” is there to lose the trailing newline I should be picking up from the :read. Since it’s just deleting whitespace, I’d be pretty surprised if it’s eating the 0/1 I am expecting back. Getting an empty string back seems odd.

–Richard

you are not passing the correct options to popen… So popen is not capturing the command output…

I use a nifty little function in my plugins to do exactly what you want…

function shellExecute(cmd, Output)
	if (Output == nil) then Output = true end
	local file = assert(io.popen(cmd, 'r'))
	if (Output == true) then
		local cOutput = file:read('*all')
		file:close()
		return cOutput
	else
		file:close()
		return
	end
end

Also, the gsub() you are using will eat all the whitespace in the output… To remove only trailing newline, try this instead:

local status = s:gsub("\r",""):gsub("\n","")

BTW: If you are trying to create a plugin… They have a (sparsely documented) HTTP API HERE that would preclude the use of SSH.

[quote=“cybrmage, post:4, topic:189369”]you are not passing the correct options to popen… So popen is not capturing the command output…

I use a nifty little function in my plugins to do exactly what you want…

function shellExecute(cmd, Output)
	if (Output == nil) then Output = true end
	local file = assert(io.popen(cmd, 'r'))
	if (Output == true) then
		local cOutput = file:read('*all')
		file:close()
		return cOutput
	else
		file:close()
		return
	end
end

Also, the gsub() you are using will eat all the whitespace in the output… To remove only trailing newline, try this instead:

local status = s:gsub("\r",""):gsub("\n","") [/quote]

Hmm. The Lua docs say that the mode argument to io.popen, if not present, defaults to “r”. So I left it out, as is the case with many examples I see in the fora here. As for the gsub, I’m only expecting one character back, aside from the newline. I’ll try adding the mode to the “popen” invocation when I get home.

Thanks for the suggestions.

-Richard

It may be a case of the SSH command or the CAT command on the remote host (the mFi outlet) not operating properly…

On the Vera command line, the SSH command outputs both STDOUT and STDERR from the remote machine.
In Vera LUA, popen only reads STDOUT.

If the remote machine is sending its output to STDERR instead of STDOUT, your lua variable will always be empty.

You may need to add redirect operators to your ssh command line…

local handle = io.popen("ssh -y -i /root/.ssh/mfi_rsa admin@192.168.1.137 cat /proc/power/relay1 2>&1")

[quote=“cybrmage, post:6, topic:189369”]It may be a case of the SSH command or the CAT command on the remote host (the mFi outlet) not operating properly…

On the Vera command line, the SSH command outputs both STDOUT and STDERR from the remote machine.
In Vera LUA, popen only reads STDOUT.

If the remote machine is sending its output to STDERR instead of STDOUT, your lua variable will always be empty.

You may need to add redirect operators to your ssh command line…

local handle = io.popen("ssh -y -i /root/.ssh/mfi_rsa admin@192.168.1.137 cat /proc/power/relay1 2>&1") [/quote]

So adding the “r” mode to io.popen makes no difference. Redirecting stderr onto stdout gets me the stderr message about the key being accepted unconditionally at the far end. But no stdout per se. Bizarre.

–Richard

try changing the command sent to popen slightly…

local handle = io.popen('ssh -y -i /root/.ssh/mfi_rsa admin@192.168.1.137 "cat /proc/power/relay1 2>&1"')

[quote=“cybrmage, post:8, topic:189369”]try changing the command sent to popen slightly…

local handle = io.popen('ssh -y -i /root/.ssh/mfi_rsa admin@192.168.1.137 "cat /proc/power/relay1 2>&1"') [/quote]

At this point, I have tried a bazliion things, including what you had suggested. I have had to prepend “export HOME=/root”, or the code doesn’t find the trusted hosts file, and therefore gets stuck waiting for someone to tell it to proceed. Well, not stuck–since the pipe was only opened for read, the request for input fails right away.

Here’s the bizarre thing: I can change the command to whatever I want, and I will get nothing back. 0 bytes. I can change the command to something that doesn’t exist (think /usr/bin/foo), and I get no errors back (and I have pitched the “-y” option to ssh to make sure I see all the wrong turns).

But if the command is “touch foobar”, that file gets created at the far end…so the ssh command works, but popen is not getting its output. As I’ve said before, this all works from the Vera command line.

Has anyone used Lua popen with ssh and gotten any readable output that wasn’t local ssh errors?

–Richard

I’m mobile so I can’t test any code now, but have you tried a popen() that doesn’t run ssh, instead running something uncomplicated and local like “/bin/echo 1”? If that produces the correct output then you’ve got strong evidence of the ssh being the culprit.

Edit: or wherever echo is on the Vera. Related: I would even be saying /bin/cat rather than just cat, because there’s no guarantee that the path is set to anything useful.

Edit edit: to distinguish differences in the environments of the Vera shell compared with the Test Lua window, put your Lua code in a file on the Vera and run it from the Vera shell with the command line Lua interpreter:

lua mytestcode.lua

This may pinpoint issues with running under a tty (shell) or not (LuaUPnP).

I just tried this from the Vera test luup code window… (with the ssh command modified to cat a file from my wink hub)…

08      10/26/15 18:52:11.345   JobHandler_LuaUPnP::HandleActionRequest device: 0 service: urn:micasaverde-com:serviceId:HomeAutomationGateway1 action: RunLua <0x740a3520>
08      10/26/15 18:52:11.345   JobHandler_LuaUPnP::HandleActionRequest argument Code=local handle = io.popen('ssh -y root@192.168.1.86 "cat /etc/passwd"')
local io_resp = handle:read("*a")
handle:close()
luup.log("io resp ["..io_resp.."]")

return true <0x740a3520>
50      10/26/15 18:52:14.111   luup_log:0: io resp [root:x:0:0:root:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:100:sync:/bin:/bin/sync
mail:x:8:8:mail:/var/spool/mail:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
localcontrol:x:82:82:local control server:/tmp:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
haldaemon:x:68:68:hald:/:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
default:x:1000:1000:Default non-root user:/home/default:/bin/sh
dbus:x:81:81:DBus messagebus user:/var/run/dbus:/bin/false
] <0x740a3520>

So… the content of the file is returned by the read from popen…

If you consistently get an empty response from the mFi outlet, I would suspect a broken SSH server on the mFi…

Have you tried using the mFi HTTP API??

[quote=“cybrmage, post:11, topic:189369”]I just tried this from the Vera test luup code window… (with the ssh command modified to cat a file from my wink hub)…

08      10/26/15 18:52:11.345   JobHandler_LuaUPnP::HandleActionRequest device: 0 service: urn:micasaverde-com:serviceId:HomeAutomationGateway1 action: RunLua <0x740a3520>
08      10/26/15 18:52:11.345   JobHandler_LuaUPnP::HandleActionRequest argument Code=local handle = io.popen('ssh -y root@192.168.1.86 "cat /etc/passwd"')
local io_resp = handle:read("*a")
handle:close()
luup.log("io resp ["..io_resp.."]")

return true <0x740a3520>
50      10/26/15 18:52:14.111   luup_log:0: io resp [root:x:0:0:root:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:100:sync:/bin:/bin/sync
mail:x:8:8:mail:/var/spool/mail:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
localcontrol:x:82:82:local control server:/tmp:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
haldaemon:x:68:68:hald:/:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
default:x:1000:1000:Default non-root user:/home/default:/bin/sh
dbus:x:81:81:DBus messagebus user:/var/run/dbus:/bin/false
] <0x740a3520>

So… the content of the file is returned by the read from popen…

If you consistently get an empty response from the mFi outlet, I would suspect a broken SSH server on the mFi…

Have you tried using the mFi HTTP API??[/quote]

Not yet (mFi HTTP API). So mFi SSH server is Dropbear, just like Vera. If this was the server on the far end, why does the command work and produce output locally from the command line? The remote server should have no inkling of whether the connection request came from the command line or code, since we’re not opening a tty in either case.

And Futzie: things do work locally.

did you use (the appropriate command for the mFi)

local handle = io.popen('ssh -y root@192.168.1.86 "cat /etc/passwd"')

(note the single quotes around the entire command an double quotes around the command to be executed on the remote machine)
This one returns data…

The original form

local handle = io.popen("ssh -y root@192.168.1.86 cat /etc/passwd")

(note the double quotes around the ssh command and no quotes around the command to be executed on the remote machine)
This one does not return any data…

[quote=“cybrmage, post:13, topic:189369”]did you use (the appropriate command for the mFi)

local handle = io.popen('ssh -y root@192.168.1.86 "cat /etc/passwd"')

(note the single quotes around the entire command an double quotes around the command to be executed on the remote machine)
This one returns data…

The original form

local handle = io.popen("ssh -y root@192.168.1.86 cat /etc/passwd")

(note the double quotes around the ssh command and no quotes around the command to be executed on the remote machine)
This one does not return any data…[/quote]

Had gone to that quoting style a long ways back. For the mFi, it seems to make no difference. No output. No matter what the command.

–Richard

So others who have seen this work: what UI and dropbear version is running on your Vera? I’m on early UI5 (still haven’t moved to V3 from V2), dropbear 0.52.

I’ve written a simple shell script that invokes “date” on a remote host via ssh. This directs its output to a local file. Using key-based auth. I run it from the shell, and I get what I’d expect in the file. I launch the script via os.execute from the Luup test window, and I get an empty file.

Changed that from pointing at the mFi to pointing at a server running Ubuntu 14.04. Run from shell, get results. Run from luup, get empty file. So I no longer can be convinced that this is something squirrelly about the mFi SSH server. I think this is something broken about the Vera LUA implementation at my rev of the box. FWIW, the dropbear version on the mFi is 0.51…even older.

–Richard