简体   繁体   中英

Python: get last command line in linux terminal

I would like to write a python script which access the last command executed in terminal, ie the command that launched the program.

For example, I want the terminal to output 'python myfile.py' if i typed python myfile.py

First I tried:

    import os
    os.system("touch command.txt")
    os.system("history > command.txt")
    with open("command.txt", "r") as f:
        command = f.read()[-1]
    print(command)

but this is not working since history is a bash built-in function.

Then I tried :

    import os, subprocess
    command = subprocess.check_output(["tail","-n","1",os.path.expanduser("~/.bash_history")]).decode("utf-8").rstrip()
    print(command)

but this does not meet my expectations, because bash history is only updated when the terminal is closed.

To improve this behavior I tried os.putenv("PROMPT_COMMAND", "history-a") , but it didn't help neither, because bash history update is still one step behind, as my variable command would now contain the command line just before python myfile.py

Now I'm stuck and I need your help pls

You can't get the original shell command line in a reliable way without participation of the shell itself, but you can generate an equivalent command line using sys.argv . (It won't include things like redirections, but if you're just re-executing from inside the existing copy of the program , all those executions will have been already performed before you're started anyhow, so when you re-exec yourself the new copy will inherit their effect).

So:

#!/usr/bin/env python
import os.path, sys
try:
    from shlex import quote  # Python 3
except ImportError:
    from pipes import quote  # Python 2

sys_argv_str = ' '.join(quote(x) for x in sys.argv)

print("We can be restarted by calling the argv: %r" % (sys.argv,))
print("As a shell-syntax string, that would be: %s" % (sys_argv_str,))
print("...or, if your shell is bash, you can specify the interpreter directly:")
print('   ' + ' '.join(quote(x) for x in (['exec', '-a', sys.argv[0], os.path.abspath(sys.executable), os.path.abspath(__file__)] + sys.argv[1:])))

If someone calls ./yourprogram "first argument" "second argument" , that output might look like:

We can be restarted by calling the argv: ['./yourprogram', 'first argument', 'second argument']
As a shell-syntax string, that would be: ./yourprogram 'first argument' 'second argument'
...or, if your shell is bash, you can specify the interpreter directly:
   exec -a ./yourprogram /usr/bin/python /home/charles/tmp/yourprogram 'first argument' 'second argument'

Note that argv[0] is not guaranteed to be identical to __file__ ! When a program is starting another program it can pass any string it likes in the argv[0] slot; it's merely convention , not a firm guarantee, that that will contain the name that was used to start the software at hand.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM