0

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?

2 Answers 2

1

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())
Sign up to request clarification or add additional context in comments.

1 Comment

This combined with process parents was what I needed in a more general case. Thank you!
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.