Python 键入的完整命令行
我想得到完整的命令行,因为它是键入的 这: .join(sys.argv[:]) 此处不起作用(删除双引号)。此外,我不希望重新加入已解析和拆分的内容Python 键入的完整命令行,python,command-line,Python,Command Line,我想得到完整的命令行,因为它是键入的 这: .join(sys.argv[:]) 此处不起作用(删除双引号)。此外,我不希望重新加入已解析和拆分的内容 有什么想法吗?在Unix环境中,这通常是不可能的……您最好希望的是传递给进程的命令行 因为shell(本质上是任何shell)在将键入的命令行交给操作系统执行之前,可能会以多种方式咀嚼命令行。你太迟了。当类型化命令到达Python时,您的shell已经发挥了它的魔力。例如,引号被使用(正如您所注意到的),变量被插值,等等。*nix 请看:流程只看
有什么想法吗?在Unix环境中,这通常是不可能的……您最好希望的是传递给进程的命令行
因为shell(本质上是任何shell)在将键入的命令行交给操作系统执行之前,可能会以多种方式咀嚼命令行。你太迟了。当类型化命令到达Python时,您的shell已经发挥了它的魔力。例如,引号被使用(正如您所注意到的),变量被插值,等等。*nix 请看:流程只看到单独的参数 您无法获取在常规情况下键入的命令行。在Unix上,shell将命令行解析为单独的参数,并最终被调用
sys.argv
来自传递给execve()函数的argv
参数。您可以使用”.join(map(pipes.quote,argv))
获得一些等价的东西,但您不需要这样做,例如,如果您想使用稍微不同的命令行参数重新启动脚本,那么sys.argv
就足够了(),请参阅
有一些创造性的(不实用的)解决方案:
- 使用gdb连接shell并对其进行查询(大多数shell能够重复相同的命令两次)-您应该能够获得与键入的命令几乎相同的命令-或者如果在进程退出之前更新了它,则直接读取其历史文件
- 使用屏幕、脚本实用程序获取终端会话
- 使用键盘记录器,获取键入的内容
窗户
在Windows上,本机CreateProcess()
接口是一个字符串,但python.exe仍然以列表形式接收参数subprocess.list2cmdline(sys.argv)
可能有助于逆转该过程list2cmdline
是为使用-python的应用程序而设计的。exe
就是其中之一list2cmdline
不会返回键入的命令行,但在本例中,它会返回等效的函数
在Python2上,您可能需要从命令行获取无法在Windows ANSI代码页(如cp1252)中表示的Unicode字符。如前所述,这可能无法完成,至少不可靠。在一些情况下,您可能能够找到shell的历史文件(例如-“bash”,但不是“tcsh”),并从中获取用户的键入。我不知道您对用户环境有多大的控制权(如果有的话)。如果您在Linux上,我建议您使用~/.bash_history
文件或shellhistory
命令,尽管我相信该命令必须在添加到shell历史记录之前完成执行
我开始玩:
import popen2
x,y = popen2.popen4("tail ~/.bash_history")
print x.readlines()
但是我有一种奇怪的行为,shell似乎没有完全刷新到.bash_history
文件。在Linux上有/proc//cmdline
的格式是argv[]
(也就是说,所有行之间都有0x00,您无法真正知道有多少字符串,因为您没有获得argc;尽管当文件的数据用完时您会知道它;)
您可以确定命令行也已经被屏蔽了,因为所有转义/变量填充都完成了,并且参数被很好地打包(参数之间没有额外的空格,等等)
commandstring = '';
for arg in sys.argv:
if ' ' in arg:
commandstring += '"{}" '.format(arg);
else:
commandstring+="{} ".format(arg);
print(commandstring);
例如:
像这样从终端调用
./saferm.py sdkf lsadkf -r sdf -f sdf -fs -s "flksjfksdkfj sdfsdaflkasdf"
将在commandstring中提供相同的字符串:
./saferm.py sdkf lsadkf -r sdf -f sdf -fs -s "flksjfksdkfj sdfsdaflkasdf"
我只是晚了10.5年才参加聚会,但是……下面是我在Linux下如何处理与OP完全相同的问题(正如其他人所说,在Windows中,可以从系统中检索信息)
首先,请注意,我使用argparse
模块来解析传递的参数。此外,参数随后被假定为作为--parname=2
,--parname=“text”
,-p2
或-p“text”
传递
它可能不能完全覆盖所有角落的情况,但它对我很有用(它甚至可以检测到像1e-06
这样的数字不需要引号)
在上面,为了检查传递给参数的值是否为“数值”,我从中偷取。您可以使用提供跨平台解决方案的psutil
:
import psutil
import os
my_process = psutil.Process( os.getpid() )
print( my_process.cmdline() )
如果这不是您想要的,您可以进一步获取父程序的命令行:
变量仍将被拆分为其组件,但与sys.argv
不同,它们不会被解释器修改。即使在.history中,也应用了一些处理(!至少替换…).1表示聪明。想法不错。我相信默认情况下,Bash不会写入.history文件,除非在会话结束时写入,因此这也不起作用。对于实际提议来说,这是可以的。但是,如果您想要获得所有的双空格或制表符,这将不起作用(这只是对命令行的良好“重建”,而不是原始命令行).Usage带有一个参数。这意味着subprocess.list2cmdline(sys.argv)
应该使用。@A.Sommerh:1-它适用于双空格和制表符。它是子流程
模块在Windows上创建新流程时使用的。Windows上的每个命令都解析自己的命令行。python.exe使用与子流程相同的规则。list2cmdline()
.2-我已经批准了您的编辑。这使我在完整的代码示例中提到了函数的名称。我并不是想暗示subprocess.list2cmdline()
是一个实际的名称sugg
import psutil
import os
my_process = psutil.Process( os.getpid() )
print( my_process.cmdline() )
my_parent_process = psutil.Process( my_process.ppid() )
print( my_parent_process.cmdline() )