键入的完整命令行

时间:2009-03-20 19:11:34

标签: python command-line

我希望获得输入的完整命令行。

此:

" ".join(sys.argv[:])

在这里不起作用(删除双引号)。此外,我不想重新加入被解析和拆分的东西。

有什么想法吗?

8 个答案:

答案 0 :(得分:26)

你来不及了。当类型命令到达Python时,你的shell已经发挥了它的魔力。例如,引用消耗(正如您所注意到的),变量得到插值等等。

答案 1 :(得分:13)

在Unix环境中,这通常是不可能的...您可以期望的最好的是传递给您的进程的命令行。

因为shell(基本上是任何 shell)可能会在将其输入操作系统执行之前以多种方式处理类型命令行。

答案 2 :(得分:9)

* nix中

查看the initial stack layout (Linux on i386) that provides access to command line and environment of a program:该过程只能看到单独的参数。

在一般情况下,您无法获得命名行,因为它是键入的。在Unix上,shell将命令行解析为单独的参数,最终调用execv(path, argv) function that invokes the corresponding syscallsys.argv派生自传递给argv函数的execve()参数。您可以使用" ".join(map(pipes.quote, argv))获得等效的东西但是您不需要例如,如果您想要使用稍微不同的命令行参数重新启动脚本,那么sys.argv就足够了(in many cases),见Is it possible to set the python -O (optimize) flag within a script?

有一些创意(非实用)解决方案:

  • 使用gdb附加shell并查询它(大多数shell能够重复相同的命令两次) - 您应该能够获得与键入的命令几乎相同的命令,或者如果之前更新了它,则直接读取其历史文件您的流程退出
  • 使用屏幕,脚本实用程序来获取终端会话
  • 使用键盘记录器来获取键入的内容。

在Windows上,本机CreateProcess()接口是一个字符串,但python.exe仍然以列表形式接收参数。 subprocess.list2cmdline(sys.argv)可能有助于扭转这一过程。 list2cmdline专为使用the same rules as the MS C runtime的应用而设计 - python.exe就是其中之一。 list2cmdline不会返回命名行,因为它是键入的,但在这种情况下返回功能等效。

在Python 2上,您可能需要GetCommandLineW(),以从命令行获取无法在Windows ANSI代码页中表示的Unicode字符(例如cp1252)。

答案 3 :(得分:5)

如上所述,这可能无法完成,至少不可靠。在少数情况下,您可能能够找到shell的历史文件(例如 - “bash”,但不是“tcsh”)并从中获取用户的输入。我不知道你对用户的环境有多少控制权。

答案 4 :(得分:1)

如果您使用的是Linux,我建议使用~/.bash_history文件或shell history命令进行修改,但我相信该命令必须在添加到shell历史记录之前完成执行。< / p>

我开始玩:

import popen2
x,y = popen2.popen4("tail ~/.bash_history")
print x.readlines()

但是我发现奇怪的行为,shell似乎并没有完全刷新到.bash_history文件。

答案 5 :(得分:0)

在Linux上有/proc/<pid>/cmdline格式为argv[](即所有行之间有0x00,你不知道有多少字符串,因为你没有得到argc;虽然你会在文件用完数据时知道它;)。

您可以确定该命令行已经被释放,因为完成了所有转义/变量填充并且参数被很好地打包(参数之间没有额外的空格等)。

答案 6 :(得分:0)

我晚了10.5年,但是...在Linux下,我处理了与OP完全相同的问题(正如其他人所说的,在Windows中,可以从中检索信息)系统)。

首先,请注意,我使用argparse模块来解析传递的参数。此外,然后假定参数以--parname=2--parname="text"-p2-p"text"的形式传递。

call = ""
for arg in sys.argv:
    if arg[:2] == "--": #case1: longer parameter with value assignment
        before = arg[:arg.find("=")+1]
        after = arg[arg.find("=")+1:]
        parAssignment = True
    elif arg[0] == "-": #case2: shorter parameter with value assignment
        before = arg[:2]
        after = arg[2:]
        parAssignment = True
    else: #case3: #parameter with no value assignment
        parAssignment = False
    if parAssignment:
        try: #check if assigned value is "numeric"
            complex(after) # works for int, long, float and complex
            call += arg + " "
        except ValueError:
            call += before + '"' + after + '" '
    else:
        call += arg + " "

它可能无法完全涵盖所有极端情况,但对我很有用(它甚至可以检测到像1e-06这样的数字都不需要引号)。

在上面,为了检查传递给参数的值是否为“数字”,我从this pretty clever answer那里窃取。

答案 7 :(得分:0)

您可以使用提供跨平台解决方案的psutil

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() )

变量仍会被拆分成其组件,但与 sys.argv 不同的是,它们不会被解释器修改。