0

I'm trying to automate the deletion of a program with python and shell scripts. this is the code I use to execute my shell scripts.

import subprocess

self.shellscript = subprocess.Popen([self.shellScriptPath], shell=True, stdin=subprocess.PIPE )
self.shellscript.stdin.write('yes\n'.encode("utf-8"))
self.shellscript.stdin.close()
self.returncode = self.shellscript.wait()

This is the shell script that I want to run.

echo *MY PASSWORD* | sudo -S apt-get --purge remove *PROGRAM*
echo *MY PASSWORD* | sudo -S apt-get autoremove
echo *MY PASSWORD* | sudo -S apt-get clean

I know it's not secure to code my password into it like this but I will fix this later.

My problem is that the commandline asks me to type y/n but the program skips that and nothing happens.

SiHa
  • 7,830
  • 13
  • 34
  • 43
Teer 2008
  • 79
  • 1
  • 7
  • 5
    The simple fix is to use the `-y` option of `apt-get`. More generally, prefer `subprocess.run` over `subprocess.Popen`; notice the `input` keyword argument. – tripleee Sep 15 '21 at 15:14
  • 2
    You cant (easily) use a list of arguments with `shell=True`; unless you _really_ know what you are doing, use either `subprocess.run('command with args', shell=True)` (but understand the [Actual meaning of `shell=True` in `subprocess`](https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess)) or `subprocess.run(['command', 'with', 'arguments])` with no `shell`. – tripleee Sep 15 '21 at 15:16
  • that works perfectly but only if I remove the last three lines self.shellscript.stdin.write('yes\n'.encode("utf-8")), self.shellscript.stdin.close(), self.returncode = self.shellscript.wait() I became the error self.shellscript has no attribute stdin. Should i worry about it? – Teer 2008 Sep 15 '21 at 15:34
  • One of the many reasons to prefer `subprocess.run` is that it replaces _all of_ your code with a single call. `self.returncode = subprocess. run(self.shellScriptPath, input='yes\n', text=True).returncode` (though the `self.` is dubious here; take it out if this isn't inside a method of a class). – tripleee Sep 15 '21 at 16:41

1 Answers1

1

In this particular case, the absolutely simplest fix is to use

apt-get -y ...

and do away with passing input to the command entirely.

In the general case, you want to avoid Popen in every scenario where you can. You are reimplementing subprocess.call() but not doing it completely. Your entire attempt can be reduced to (and fixed with)

self.returncode = subprocess.run(
    self.shellScriptPath, input='yes\n', text=True).returncode

Unless the commands in self.shellScriptPath require a shell, probably remove shell=True and, if necessary, shlex.split() the value into a list of tokens (though if it's already a single token, just split it yourself, trivially: [self.shellScriptPath]).

tripleee
  • 175,061
  • 34
  • 275
  • 318