The do_shell() is not working correctly with multiple commands
See original GitHub issueWhen I call do_shell() with multiple commands using
- “;”.join(commands) - it only executes the first command
- “&&”.join(commands) - it throws an exception
Given the following script (which has all of the details), you can see the behavior I’m seeing.
#!/usr/bin/env python
"""A simple cmd2 application."""
import cmd2
class App(cmd2.Cmd):
"""
A simple cmd2 application. Copied from "Basic Commands" in the manual.
I had a LOT of Cmd apps/scripts that I was using and then converted most
of them to use Cmd2 and all was working fine with this type of formatting,
(i.e. multiple commands in a string).
At some point, after updating to different versions of cmd2, many of my
commands started breaking like this one does.
I can run SINGLE commands, but not multiple ones -- especially when I just
"join" them from multiple lines to one line. Note though, in the "works"
command, I use just a string passed into *do_shell* and it works, which
surprised me. If I try that with a ";" as the seperator, it does not work,
which is what happens in the "fail1" and "fail2" commands.
I haven't dived into the why, but was able to replicate it quite easily in
something that is pretty small (the comments and me explaining it are
probably going to be much longer than the actual code).
Both failures should work just fine, as they are commands that will work
from:
* the bash prompt
* the Cmd2 shell prompt (i.e. using !<command>)
* the Cmd.do_shell() function (using Cmd, not Cmd2)
I use commands like this all the time. Cmd's do_shell() handles
this as expected. Even Cmd2's command prompt handles the exact same
commands just fine.
If I type something like the following commands, FROM the Cmd2/App command
prompt, they work as expected, so ...
- !echo "hi";echo "there";echo "cmd2"
- !echo "hi"&&echo "there"
- !ls && echo "-----done-----"
I'm not sure where a regression came in at. If needed, I can go back to
the different versions that I'm pretty sure it was working and give it a
try.
This used to work in Cmd2 as well, until a little while ago. I've not
narrowed down the exact date, but I think it's sometime around the new
addition of the CommandSet changes (which I was surprised to find and
wanted to use).
It was around that time (after CommandSet introduction to the code base),
so pretty sure it's after v1.2.1. It's probably after v1.3.0 or v1.3.1, as
I had it working and didn't see any problems with it. Multiple commands
doing just this were added at around that time as well.
I THINK was after v1.3.1, around the time that the CommandSet stuff broke
backward compatibility with itself (as I remember thinking I didn't realize
I was working on such the cutting edge! ;-) ) and I skipped at least one
version if not more, so can't say when, for sure, it broke this functionality.
It was definitely broken after v1.3.4. I upgraded to v1.3.5 today
(2020-08-27) to see if it had been fixed. I wasn't terribly surprised that
it still was broken.
Now for some system information:
OS: macOS Catalina v10.15.5
Python: v3.8.0
Cmd2: v1.3.5
"""
# common commands to show problem
cmds = [
'echo "hi"',
'echo "there"',
'echo "cmd2!"'
]
def __init__(self):
super().__init__()
self.debug = True
def _printMessage(self, cmd):
print(f"\n\n-----cmd=[{cmd}]-----")
print("this fails in 'self.do_shell(cmd)'")
print(f"BUT, it works if you do [!{cmd}] from the (Cmd) prompt\n\n")
def do_fail1(self, statementObj):
# this should work (and used to work),
# but ONLY executes the FIRST command - ignores the rest
cmd = ';'.join(self.cmds)
self._printMessage(cmd)
self.do_shell(cmd)
def do_fail2(self, statementObj):
# this should also work - better bash 'best practice' anyway
# this just fails though
cmd = '&&'.join(self.cmds)
self._printMessage(cmd)
self.do_shell(cmd)
def do_works(self, statementObj):
print("\n")
self.do_shell('echo "this works just fine!"')
print("\nas does this! \n")
self.do_shell('ls -la')
print("\nthis surprisingly DOES work -- not sure why :-( \n")
self.do_shell('ls&&echo "-----done-----"')
print("\n")
if __name__ == '__main__':
import sys
c = App()
sys.exit(c.cmdloop())
Thanks! Mike
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:16 (9 by maintainers)
Top Results From Across the Web
kstenschke/doShell: Headful automation on Linux and Mac OS
What does it do? Functional Flow; Runtime options. Flags; Conditional blocks. Macros; Commands. Mute output; Import; Ivoke PHP and Node.js; String manipulation.
Read more >Shell script failing in Automator but works if I copy/paste into ...
ico into Terminal and everything will work fine. Any idea why Automator can't seem to find this command? Even though line 12 may...
Read more >"Do Shell Script" command in applescript works in script editor ...
The problem I am running into is that the script works just fine when I ... to RESETPASSIND_PASSWORD's stringValue() as text do shell...
Read more >Commands Reference - Apple Developer
Commands Reference. This chapter describes the commands available to perform actions in AppleScript scripts. For information on how commands ...
Read more >Command Line - Scripting OS X
In this post we are going to explore a different, but very common way to launch shell commands and scripts: AppleScript's do shell...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

@legacy-code If you want both the ability to chain shell commands with semicolons and plan to have multiline commands, then just choose another terminator character.
Nevermind, I see you provided that info.