What is a common/practical use of Popen.wait() - python-2.7

I am trying to understand this line of Code:
def delete_dir(dir):
with open('/dev/null', 'w+') as null:
subprocess.Popen("rm -r %s" % dir, shell=True, stdout=null, stderr=null).wait()
I'm new to programming so I lack the context to understand why this process is set to wait. What are some common practice implementation to setting a process to wait. Thanks

Popen.wait doesn't tell the process to wait, it tells our script to wait for the process to terminate before continuing execution. This is useful whenever the child process is doing something that will affect the behaviour of our script.
In this case, we are waiting for the rm -r command to finish deleting the given directory before we continue, because if our function is called delete_dir it is reasonable for the caller to expect the directory to be deleted before the function returns.
The purpose of with open('/dev/null', 'w+') as null (if you are curious) is to suppress any output of the child process by piping its stdout and stderr to the /dev/null handle.

Related

How to force quit my python-made exe

I've got a little python app that I used pyInstaller on to create an exe file:
import subprocess
try:
taskCommand = 'tasklist /FI "ImageName eq pc-client.exe"'
reply = subprocess.Popen(taskCommand, stdout = subprocess.PIPE).communicate()[0]
for line in reply.split("\n"):
if line.startswith("pc-client.exe"):
PID = line.split()[1]
print PID
except:
pass
try:
killCommand = ("TASKKILL /f /t /PID " + PID)
subprocess.Popen(killCommand, stdout = subprocess.PIPE).communicate()[0]
except:
pass
try:
print "Restarting Papercut Client..."
subprocess.Popen(r"\\server\path\to\file\filename.exe", stdout = subprocess.PIPE).communicate()[0]
except:
pass
sys.exit()
When the exe is run, it opens up in the windows command window, will run its code (it's non-interactive) and then I want the window to dissappear when its finished!
What should I put at the end of my python code to make the window close when completed. I've tried os.quit(), os._exit(), sys.quit() & sys.exit() but none of them actually close the window!
As I'm creating an exe from my code, should I use something else? I can't compile with the noconsole flag, as it needs it to actually run the commands...
Thanks.
You can block the windows command prompt from coming up at all by putting
console=False
in your spec file. For example:
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='YourApp',
console=False,
icon='IMGFolder\game_icon_cs6_icon.ico')
If you are running from the command line without a spec file, use the noconsole flag:
pyinstaller.py --noconsole yourscript.py
for more info on the PyInstaller options: https://pyinstaller.readthedocs.io/en/stable/usage.html#options
If you want the prompt to come up then close, sys.exit() works for me, but without seeing more code it will be hard to tell.
UPDATE
Since subprocesses are involved, keep in mind that the command prompt will remain open until all processes are resolved (parent and child).
It looks like you are killing the first task with its PID (I would print out the PID before you kill it to confirm you have the right one). Then you run the second task (the main file you want run?) but never kill it.
Are you trying to close the command prompt but keep the .exe running?
There is some good information about killing processes here:
How to kill a python child process created with subprocess.check_output() when the parent dies?

Is std::system or exec better practice?

I have a program that calls a shell script tool that I made that goes through a directory and zips up files and gets the checksum value and calls some other tools to upload the files. The operation takes roughly 3 to 4 minutes.
I call the script like this:
int result = system("/bin/sh /path/to/my/script");
I've also got the same result by using the exec() family of functions:
int child = fork();
if(child == 0) {
execl( "/bin/sh", "sh", "/path/to/my/script", (char*)0 );
}
I know with exec you can redirect output to the parent program so it can read the output of the command line tools, but other than that when should you use system as opposed to exec?
Ignoring for the time being that use of system is portable while use of exec family of functions is not portable...
When you combine use of exec family of functions with other POSIX functions such as pipe, dup, wait, you get a lot more control over how to pass data between the parent process and the child process.
When you don't need any of those controls, i.e. you just want to execute a command, then using system is preferable, IMO.
The first system call in your question will do the same, what you are doing in the next piece of code (fork and execl)
From documentation:
The system() library function uses fork(2) to create a child process
that executes the shell command specified in command using execl(3)
http://man7.org/linux/man-pages/man3/system.3.html

How to kill process in c++, knowing only part of its name

Some time ago I needed to write c++ code to kill some process. In my main program I run large CAE-system package with system("...") with different filename strings on input. CAE-software creates many processes, that contain in process name string filename). Some of the CAE-processes worktime > max_time, than I need to shut them down:
//filename contains part of CAE-process name
string s="/bin/kill -9 `ps aux | grep "+filename+" | awk {'print $2'}`";
system(s.c_str());
The output was:
Usage:
kill pid ... Send SIGTERM to every process listed.
kill signal pid ... Send a signal to every process listed.
kill -s signal pid ... Send a signal to every process listed.
kill -l List all signal names.
kill -L List all signal names in a nice table.
kill -l signal Convert between signal numbers and names.
I tried to run with execvp, tried different ways running kill or pkill over bash script, calling system("name_of_script.sh"), where script contained kill -9 *filename* but the result was the same.
Using kill and /bin/kill gave the same output, bash -c kill... too.
Using kill from my system (Ubuntu Natty) gnome-terminal:
kill -9 `ps aux | grep filename | awk {'print $2'}`
shutdown all necessary processes! It works.
When using pkill, as I could understand, we need full process name to kill it, but I have only part of name.
I also tried to wrap computational process into a child thread using pthreads and stop it with pthread_cancel, but it doesn't work because of CAE-system process doesn't receive signals (I think, trapping them), the only way is SIGTERM.
Killing child-thread-"wrap" with pthread_kill also kills the parent (my main program).
I don't know CAE-process pids to call kill from signals.h
Closing main program do not stop CAE-processes (and the do not have -Z flag, so are they aren't my program process childs??)
How can I close CAE-processes, that run > MAXTIME from my main program?
The problem was that I was running main program via debugger (gdb) in QtCreator. Without QtCreator shell-script runs with arguments the right way, though arguments are passed correctly both ways.
Also I have to clear some CAE processes, that don't have filename in cmdline, but that are parents or children of this process.
In shell-script you can use:
cat /proc/"$P"/status | grep PPid | grep -o "[0-9]*"
where $P is a variable with pid of killed process.
Here are several methods to kill all child processes.
I'll write smth. similar in C++ that will scan /proc/xxxx/status till PPid= ppid_of_my main_program and cut that branch.
You don't have to open a shell to kill a process. Just use the "kill" function:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
http://linux.die.net/man/2/kill
To find a process to kill read the following directory:
/proc/####/cmdline
Where #### is the number of any running process id. So the code roughly would be to read the /proc directory and list out all the numerical directories, these are the current running processes, and you find the name of the command that spawned that process in the "cmdline" file in that directory. You can then use a regular expression, or a string comparison to identify processes to kill.
This should just work assuming filename isn't too much exotic or contains a regular expression pattern:
string s="pkill -9 -f "+filename";
system(s.c_str());
As a side note, -9 is a last resort signal, not something you should start with. I would thus recommend the less brutal:
string s="pkill -f "+filename"+";sleep 2; pkill -9 -f "+filename;
system(s.c_str());

started from command line?

I have a simple C/CPP process running on a linux system. This is a.out.
Another process is capable to start a.out inside its code. This is b.out.
What code do I need inside a.out to understand that it is executed from the command line?
Eg ./a.out
Is there a way a process to know if it started from the cmd or started from another process?
You can't find out in general whether a program was started "from the command line" (by a user's explicit command), but you can find out whether its standard input and output are talking to a terminal/command window:
#include <unistd.h>
isatty(fileno(stdin))
and stdout return whether standard input/standard output are terminals.
If you need to know what process starting your program, use the getppid system call to get the parent's process ID (ppid), then read the pseudo-file /proc/ppid/cmdline.
You can check its parent task ID, using getppid()
You can do multiple things, but none will be 100% reliable:
isatty(0) to check whether standard input is a TTY terminal,
check for the parent task ID (getppid()), then lookup the parent's PID to match it against its executable's path (using whatever you want. a call to ps and some parsing could do, or have fun using /proc/)
you could also just have a look at the environment variables set up. do a printout of all the values contained in the env. To do that, either use the extern environ variable:
extern char **environ;
or modify your main() prototype to be:
int main(int ac, char **av, char **environ)
I would set an environment variable, in the parent process, to some value (say the parent pid), and have the child process check for it.
It is unlikely that a shell user would set this variable (call it something unlikely to name-clash), so if this variable is set to the expected value, then you know that it is being started from the parent process.
You can check whether its standard input is a terminal:
if(isatty(0)) { ... }
In short: you can't doing it directly.
In long: look you can check the getppid() value and compare it with the bash PID orb.out PID
TO search for a process inside the process table with Known PID with C you can do this:
1) get the PPID of a.out and search with this value in /porc and then if you find the folder check the cmdline file and check if this process is b.out or shell process.
2) you can deal with sysctl system call and dealing with kernel param's(you can google it)
3)
pid_t ppid = getppid();
system("pidof bash > text.in");
the system will get the pid of any shell process and write the result to text.in file
it contains all bash PID's space separated you can compare this values with getppid() value.
Good Luck.

How to get forkpty/execvp() to properly handle redirection and other bash-isms?

I've got a GUI C++ program that takes a shell command from the user, calls forkpty() and execvp() to execute that command in a child process, while the parent (GUI) process reads the child process's stdout/stderr output and displays it in the GUI.
This all works nicely (under Linux and MacOS/X). For example, if the user enters "ls -l /foo", the GUI will display the contents of the /foo folder.
However, bash niceties like output redirection aren't handled. For example, if the user enters "echo bar > /foo/bar.txt", the child process will output the text "bar > /foo/bar.txt", instead of writing the text "bar" to the file "/foo/bar.txt".
Presumably this is because execvp() is running the executable command "echo" directly, instead of running /bin/bash and handing it the user's command to massage/preprocess.
My question is, what is the correct child process invocation to use, in order to make the system behave exactly as if the user had typed in his string at the bash prompt? I tried wrapping the user's command with a /bin/bash invocation, like this: /bin/bash -c the_string_the_user_entered, but that didn't seem to work. Any hints?
ps Just calling system() isn't a good option, since it would cause my GUI to block until the child process exits, and some child processes may not exit for a long time (if ever!)
If you want the shell to do the I/O redirection, you need to invoke the shell so it does the I/O redirection.
char *args[4];
args[0] = "bash";
args[1] = "-c";
args[2] = ...string containing command line with I/O redirection...;
args[4] = 0;
execv("/bin/bash", args);
Note the change from execvp() to execv(); you know where the shell is - at least, I gave it an absolute path - so the path-search is not relevant any more.