我想写一个python脚本,访问终端中执行的最后一个命令,即启动程序的命令。
例如,如果我键入python myfile.py
,我希望终端输出"python-myfile.py">
我第一次尝试:
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)
但这是不起作用的,因为history是一个bash内置函数。
然后我尝试了:
import os, subprocess
command = subprocess.check_output(["tail","-n","1",os.path.expanduser("~/.bash_history")]).decode("utf-8").rstrip()
print(command)
但这并没有达到我的预期,因为bash历史记录只有在终端关闭时才会更新。
为了改进这种行为,我尝试了os.putenv("PROMPT_COMMAND", "history-a")
,但它也没有帮助,因为bash历史更新仍然落后一步,因为我的变量命令现在将包含python myfile.py
之前的命令行
现在我被困了,我需要你的帮助,请
如果没有shell本身的参与,您无法以可靠的方式获得原始shell命令行,但您可以使用sys.argv
生成等效的命令行。(它不包括重定向之类的内容,但如果您只是从程序的现有副本内部重新执行,那么在启动之前,所有这些执行都已经执行过了,所以当您自己重新执行时,新副本将继承它们的效果(。
因此:
#!/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:])))
如果有人调用./yourprogram "first argument" "second argument"
,输出可能看起来像:
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'
请注意,argv[0]
是,而不是保证与__file__
相同!当一个程序启动另一个程序时,它可以在argv[0]
插槽中传递它喜欢的任何字符串;这只是惯例,而不是一个坚定的保证,它将包含用于启动手头软件的名称。