0

I am trying to execute the command below using Popen(shlex.split(cmd)... and Popen(cmd.split(' ')...but running into errors below, how else can I run this command or how to debug this error?

def function_create_cmds(cmd):
    print cmd
    #proc = Popen(shlex.split(cmd), shell=True, stdout=PIPE, stderr=PIPE)
    proc = Popen(cmd.split(' '), stdout=PIPE, stderr=PIPE)
    (output, error) = proc.communicate()
    return output,error

cmd = "/usr/local/bin/xbs submitproject -notesfile /Users/usernamea/autosubmissionlogs/07162018_133945/milestone/project-375/project-375.plist  -version project-1.0.7 /Users/usernamea/wifiroots/project Release"
(output,error) = function_create_cmds(cmd)
print output
print error

Error:

Popen(cmd.split(' '),

INFO: submitproject was unable to locate a submission directory named 



Popen(shlex.split(cmd)
xbs requires a command
user3508811
  • 847
  • 4
  • 19
  • 43
  • 1
    Recieve your command as an array, not a string. – Charles Duffy Jul 17 '18 at 16:17
  • 1
    `cmd` as string seems already not good, or else split would have worked. materialize your arguments in a list, don't pass a string. – Jean-François Fabre Jul 17 '18 at 16:18
  • @CharlesDuffy - am taking the cmd as string but using `shlex.split(cmd)` without `shell=True`which still doesnt work – user3508811 Jul 17 '18 at 17:11
  • "doesn't work" doesn't really tell us anything useful. Give us the post-split list, **and** a working shell command line, and we could tell you something. (Though I advise against using `shlex.split(cmd)` -- it's significantly worse than an explicit list, as the explicit list will work with filenames with spaces and the like, whereas `shlex.split()` requires them to be escaped). – Charles Duffy Jul 17 '18 at 17:14
  • how do I print the `post-split list` ?command @ `"/usr/local/bin/xbs submitproject -notesfile /Users/usernamea/autosubmissionlogs/07162018_133945/milestone/project-375/project-375.plist -version project-1.0.7 /Users/usernamea/wifiroots/project Release"` works when tried from command line – user3508811 Jul 17 '18 at 17:15
  • 1
    So, if you're passing `cmd.split(' ')`, then `print(repr(cmd.split(' ')))` in your code, and [edit] the output into your question. If you're using `shlex.split(cmd)`, likewise, [edit] the output of `print(repr(shlex.split(cmd)))` into the question. – Charles Duffy Jul 17 '18 at 17:16
  • Also, is your username **really** `usernamea`? If your real names contain spaces or special characters, and what you're passing here doesn't, then you're hiding the problem's cause. – Charles Duffy Jul 17 '18 at 17:17
  • @CharlesDuffy - removing `shell=True` actually worked but sometimes one of the command hangs because the executable is waiting on a userprompt ,Is there a way to add a timeout and save the output until the timeout – user3508811 Jul 18 '18 at 03:27
  • Is it prompting through `/dev/tty` or through stdin? If you just pass a closed FD on stdin, that may prevent it from waiting on a prompt at all; `stdin=PIPE`, and then `communicate('')` should have that effect. Otherwise -- yes, it can be done, but is probably a topic for its own question. – Charles Duffy Jul 18 '18 at 13:25
  • (Generally speaking, well-written programs *should* be able to accept programmatic input rather than prompting -- you'll note the ubiquity of `--batch` style command-line arguments for the purpose; it's also not unheard of to be able to take arguments that would otherwise be prompted for through the environment. If the command is something you/your team wrote, and it doesn't handle the stdin-isn't-a-TTY case gracefully, maybe consider amending it?) – Charles Duffy Jul 18 '18 at 13:27
  • @CharlesDuffy - Unfortunately can't change the command,its not something I own or the team that owns won't change it so easily...need a way to gracefully exist in hug scenarios..timeout is one option, how so I add this timeout option? or you suggest any better way? – user3508811 Jul 18 '18 at 18:04
  • Did you actually try `stdin=PIPE`, and `communicate('')`, yet? If you use that combination, any attempt to read from stdin will immediately have an EOF, which should cause it to fail -- so you don't **need** a timeout at that point. – Charles Duffy Jul 18 '18 at 18:11
  • But yes, there are a few ways to add a timeout. One that comes to mind is to have a Python timer thread that signals the process after a given amount of time; another is to use the external `timeout` command if your OS provides one; some other variants come to mind as well, but that's probably best as a topic for a different question. – Charles Duffy Jul 18 '18 at 18:13

1 Answers1

0

Don't use shell=True it needlessy invokes a shell to run your subprocess, thus calling two processes for no benefit.

proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE)

Should work. If it doesn't, please provide the error you're getting in this case.

You could always split the command yourself:

subprocess.Popen([
    "/usr/local/bin/xbs",
    'submitproject',
    '-notesfile',
    '/Users/usernamea/autosubmissionlogs/07162018_133945/milestone/project-375/project-375.plist',
    '-version',
    'project-1.0.7',
    '/Users/usernamea/wifiroots/project',
    'Release',
])
nosklo
  • 217,122
  • 57
  • 293
  • 297
  • Trying without `shell=True` just hangs the script ,dont see any error, how else can we debug this? – user3508811 Jul 17 '18 at 17:13
  • If you're using `shell=True` with a list where the first argument isn't a script that refers to its argument list, then every argument but the first is ignored, which... well, completely explains your error message. – Charles Duffy Jul 17 '18 at 17:15
  • removing `shell=True` actually worked but sometimes one of the command hangs because the executable is waiting on a userprompt ,Is there a way to add a timeout and save the output until the timeout – user3508811 Jul 18 '18 at 03:25