如何在cmd中传递带有特殊字符的密码?

时间:2016-03-31 12:40:02

标签: cmd escaping special-characters

我正在使用plink来ssh到许多服务器并执行命令。但是,当密码有特殊字符时,无法在控制台上执行命令。

用法:plink.exe -ssh -pw "password" user@myhost "command to execute"

apof~!@#$%^&*()_+{}|:"sdfsdfs!df - 使用"转发\时取得成功。

apof~!@#<>$%^&*()_+{}|:"sdfsdfs!df - 使用"转发\时取得成功。

apof~!@#$%^&*()_+{}|:"<>sdfsdfs!df - 失败。使用"转义\。失败消息:&gt;这时出人意料。

apof~!@#$%^&*()_+{}|:"><sdfsdfs!df - 失败。使用"转义\。失败消息:&lt;这时出人意料。

apof~!@#$%^&*()_+{}|:"<sdfsdfs!df - 失败。使用"转义\。失败消息:系统找不到指定的路径。

apof~!@#$%^&*()_+{}|:">sdfsdfs!df - 失败。使用"转义\。失败消息:系统找不到指定的路径。

<之后看起来>"时,转义不起作用。很多我知道如何处理这个问题?

1 个答案:

答案 0 :(得分:0)

意识到问题不在于使用plink来转义特殊字符,而是使用cmd如何处理特殊字符。为此,我创建了一个简单的Java类来获取命令行参数并打印它:

public class MyTest {
    public static void main(String args[]) {
        System.out.println(args[0]);
    }
}

我将带有特殊字符的输入传递给此应用程序,这是输出:

    C:\>java MyTest "apof~!@#$%^&*()_+{}|:"<>?-=`[]\;',./sss"
    > was unexpected at this time.

    C:\>java MyTest "apof~!@#$%^&*()_+{}|:\"<>?-=`[]\;',./sss"
    > was unexpected at this time.

    C:\>java MyTest "apof~!@#$%^&*()_+{}|:\"^<^>?-=`[]\;',./sss"
    apof~!@#$%^&*()_+{}|:"<>?-=`[]\;',./sss

    C:\>java MyTest "apof~!@#$%^&*()_+{}|:\"^<^>?-=`[]\;',./s\"sasfafds"
    apof~!@#$%^&*()_+{}|:"<>?-=`[]\;',./s"sasfafds

    C:\>java MyTest "apof~!@#$%^&*()_+{}|:\"^<^>?-=`[]\;',./s\"sasf<>afds"
    apof~!@#$%^&*()_+{}|:"<>?-=`[]\;',./s"sasf<>afds

    C:\>java MyTest "apof~!@#$%^&*()_+{}|:\"^<^>?-=`[]\;',./s\"sasf<>af\"ds"
    apof~!@#$%^&*()_+{}|:"<>?-=`[]\;',./s"sasf<>af"ds

    C:\>java MyTest "apof~!@#$%^&*()_+{}|:\"^<^>?-=`[]\;',./s\"sasf<>af\"dasd<>fs"
    > was unexpected at this time.

    C:\>java MyTest "apof~!@#$%^&*()_+{}|:\"^<^>?-=`[]\;',./s\"sasf<>af\"dasd^<^>fs"

    apof~!@#$%^&*()_+{}|:"<>?-=`[]\;',./s"sasf<>af"dasd<>fs

    C:\>java MyTest "apof~!@<>#$%^&*()_+{}|:\"^<^>?-=`[]\;',./s\"sasf<>af\"dasd^<^>fs"
    apof~!@<>#$%^&*()_+{}|:"<>?-=`[]\;',./s"sasf<>af"dasd<>fs

根据此分析,我们发现,只有" 才能转义的特殊字符<>符号出现在"之后还必须使用^进行转义。 This document向我指出逃生部分。

下面是我为生成转义参数而编写的python函数:

def escapepassword(initpassword):
    passsplit = list(initpassword)
    quotesflag=False
    index = -1
    for token in passsplit:
        index += 1
        if quotesflag and (token in ("<", ">")):
            passsplit[index] = "^" + token
        else:
            if token == '"':
                passsplit[index] = "\\\""
                quotesflag = not quotesflag
    return "".join(passsplit)

我仍然遇到使用转义参数调用可执行文件的问题。我使用以下执行命令的方式:

subprocess.Popen('plink.exe -ssh -batch -pw' + escapepassword(password) + ' ' + username + '@' + ipaddress + ' "' + command + '"', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

或者用Java来说,它将是:

Runtime.getRuntime().exec("plink.exe -ssh -batch -pw" + escapepassword(password) + " " + username + "@" + ipaddress + " \"" + command + "\"");

这给了很多麻烦。 python或Java执行过程的方式是不同的。特殊字符被转义并传递给进程。因此,它会产生更多问题。为了解决这个问题,我将上面的代码更改为:

commandtoexecute = ['plink.exe', '-ssh', '-batch', '-pw', password, username + '@' + ipaddress, command]
subprocess.Popen(commandtoexecute, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

在Java中,可以写成:

Runtime.getRuntime().exec(new String [] {"plink.exe", "-ssh", "-batch", "-pw", password, username + "@" + ipaddress, command);

这里,命令之间有空格,例如ls -al,但这是传递参数以启动进程的方法。当我尝试在"之间传递命令时,它发出了错误,指出找不到命令,因为"也被传递以在远程系统上执行。

注意: 我使用命令WMIC path win32_process get name,Commandline | find "plink.exe"来查看命令行参数。输出是html转义的,但是,它有助于找到传递的参数。