Home > Software design >  Print parent shell process within python
Print parent shell process within python

Time:09-04

I want to log the parent command which ultimately executed my Python script. I want to captured it within the Python subprocess so I may include it in existing logs.

I have a shell script run.sh containing:

#!/bin/bash

python runme.py "$@"

And runme.py contains:

import sys
import subprocess

print("Doing stuff...")

# What command called me?
psoutput = subprocess.check_output(['ps', '--no-headers','-o','cmd'], text=True)
cmds = psoutput.strip().split('\n')
print(cmds[0])

I execute this from my company's shell (on RHEL) like this, and it outputs...

$ ./run.sh arg1 arg2 arg3
Doing stuff...
run.sh arg1 arg2 arg3

Looks good! But if another process is running first, it shows up first in ps and this doesn't work:

$ sleep 10s &
$ ./run.sh arg1 arg2 arg3
Doing stuff...
sleep 10s

I'm really trying to select my parent process from ps. This solution uses -C <process-name> but I don't know what my process name is. Following this solution I've tried this with several similar ideas for process name:

subprocess.check_output(['ps', '-o', 'ppid=', '-C', 'python runme.py'], text=True)

But that outputs a lot of numbers that look like PID's, but none seem related to my bash call.

How can I reliably get my parent process from within Python?

CodePudding user response:

One (okay) solution I realized while writing my question:

run.sh contains

command_run=$(echo "$BASH_SOURCE $@")
runme.py --command-run "$command_run" "$@"

runme.py contains

import argparse

parser = argparse.ArgumentParser()
parser.add_argument(
    '-c', '--command-run', required=False,
    default=None, dest='command_run',
    help='Command text passed from bash'
)
args = parser.parse_args()

print("Doing stuff...")
print(args.command_run)

Additional arguments can be passed after adding more parsing. As above, the following works now:

$ sleep 5s &
$ ./run.sh
Doing stuff...
run.sh

I'll mark this answer as correct unless someone has a nicer solution than passing $BASH_SOURCE this way.

CodePudding user response:

Pure python solution. It works under any shell. The parent cmd line result is a list with the command and the arguments.

import psutil
import os

ppid = psutil.Process(os.getppid())
print(ppid.cmdline())
  • Related