Home > Net >  Python script automatic intecaction without 'expect' or 'pexpect'
Python script automatic intecaction without 'expect' or 'pexpect'

Time:05-26

I'm trying to write a python script that call a BASH script with user interaction. For security reason, I can't install expect or pexpect on any server (we have very strict policies).

The BASH script is present on multiple server (called via ssh), so modifing this script is not an option as well.

my problematic part with the bash script is this:

echo ""
echo "Are you sure you want to continue and $1 the session?"
echo ""
echo -e "Press enter to continue or CTRL-C to abort...\c"
echo -e "Press enter to continue or CTRL-C to abort..."
read line
echo ""
echo "Are you ABSOLUTELY positive?"
echo ""
echo -e "Press enter to continue or CTRL-C to abort...\c"
read line
echo ""

Then from python, for now I tried multiple options either with subprocess.run() and subprocess.Popen()

I went through all these posts: How do I write to a Python subprocess' stdin?

How to make python script press 'enter' when prompted on Shell

Constantly print Subprocess output while process is running

How to make python script press 'enter' when prompted on Shell

None of it seems to work. All my best attempt can print the file of Popen.stdout and then seems to hang at

read line

And even if I do somethine like:

with subprocess.Popen("confirm.sh", shell = False, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, universal_newlines = False) as con:
    try:
         for line in iter(con.stdout.readline, ""):

            if "enter" in line.decode().strip().split():
                print(line.decode().strip())
                sleep(2)
                con.stdin.write('\n')  # or con.communicate('\n')

I get this error "I/O operation on closed file." or the script hang depending on the method.

Everytime, subprocess.run() or subprocess.Popen() look like to want to complete the process and doens't allow to interaction like pexpect.spawn() would do.

Any idea ?

CodePudding user response:

Two options come to mind:

  1. use the shell to send the input:
con = subprocess.Popen("{ echo; echo; } | ./confirm.sh", shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, universal_newlines = False)

The main change being the { echo; echo; } | bits that send two newlines to ./confirm.sh's input stream and the change to shell = True

  1. Use python's communicate method to send two newlines to stdin:
con = subprocess.Popen("./confirm.sh", shell = False, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, universal_newlines = False)
out, err = con.communicate(input='\n\n')

Hat tip to Julia Schwarz's answer for the communicate(input='\n') part.

CodePudding user response:

Thanks for the quick answer. I was so close. All I was missing( from your second option) is a second '\n' for con.communicate()

But both options seems to work. I now have to test in production... You really save me a headache.

  • Related