0

I followed this question I have this function in PostgreSQL:

CREATE OR REPLACE FUNCTION a()
  RETURNS void AS
$BODY$
import subprocess
cmd1 = "usr/bin/ssh [email protected] time"
out1, err1 = subprocess.Popen(cmd1,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE).communicate()
plpy.notice(out1)
$BODY$
  LANGUAGE plpythonu VOLATILE

This should login to the server specified and display its time. No matter what I do I always get :

ERROR: OSError: [Errno 2] No such file or directory

The only time I don't get the error is if cmd1 = "usr/bin/ssh" but then it does nothing.

How can I make it work?

4
  • I think that the path to the ssh command should start with the root folder - /usr/bin/ssh. Without the leading slash it would be a relative path - perhaps this is why the "No such file or directory" error is being raised. Commented Mar 13, 2017 at 14:21
  • 3
    cmd1 should look more like: cmd1 = ['/usr/bin/ssh', '[email protected]', 'time']. This is (if i'm not mistaken) because Popen() assumes the command parameter is a list unless dangerously supplying shell=True. You can also use cmd1 = shlex.split("/usr/bin/ssh [email protected] time"). Commented Mar 13, 2017 at 14:22
  • @Torxed this prevent the error however nothing is printed to the screen Commented Mar 13, 2017 at 14:32
  • @avi most likely because the host running the script, isn't allowed to SSH without a password - or plpy.notice() wan't a string? If SSH is hanging waiting for a password, .communicate() will hang and wait as per described in the doc as well: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. >>>Wait for process to terminate.<<<. Have you tried running this command from the server manually once to see what happens? Commented Mar 13, 2017 at 14:36

1 Answer 1

1

The problem you're facing is that Popen() assumes the command to be a list of command+arguments.

There for, cmd1 should look more like:

cmd1 = ['/usr/bin/ssh', '[email protected]', 'time']

(unless dangerously supplying shell=True, then you can keep your command string as is).

You can also use:

import shlex
cmd1 = shlex.split("/usr/bin/ssh [email protected] time")

This is also covered under the docs for Popen().

Last notes: I've never used plpythonu or this SQL version of code execution, but I'd assume that you would want to specify the full path for SSH as Lix pointed out, that being /usr/bin/ssh and not usr/bin/ssh. But your main problem is how you pass the arguments to Popen().

Don't forget to allow SSH to login with a key, otherwise the command might hang asking for a password in the background.

Seeing as many people have issues running system commands that hangs without the programmer understanding why, try the following modification to get output as the command is executed instead of at the end (.communicate() will wait for EOL, meaning hang forever if the process never quits):

CREATE OR REPLACE FUNCTION a()
  RETURNS void AS
$BODY$
import subprocess
cmd1 = ["usr/bin/ssh", "[email protected]", "time"]
process = subprocess.Popen(cmd1,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.STDOUT).communicate()
while process.poll() is None:
    plpy.notice(process.stdout.readline())
$BODY$
  LANGUAGE plpythonu VOLATILE

It's still highly inefficient since i fused STDERR and STDOUT together and using readline() instead of read(). Also import select might be useful here.

But this will give you output "live" from the command instead of bunkered up at the end. It should also print any errors that the command is throwing (but still hanging because the error didn't close the application properly).

This is a common mistake and people aught to read the examples/docs more on this.

Sign up to request clarification or add additional context in comments.

2 Comments

I have no actual need for the command to be string. I'll use the list method. How can I know if the option was successful are there any error codes?
@avi I suggest you try the code and see if there's any errors. The last edit I gave should print any errors. If there are any, correct them. But I can't in advance know if there'll be any errors ^^ If it didn't work, I suggest you create a new question that is in regards to that specific problem, seeing as this was a Popen() usage problem thread :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.