Windows OpenSSH 匹配带有嵌入引号的执行字符串

Windows OpenSSH 匹配带有嵌入引号的执行字符串

在 Windows 版 Openssh 下,是否有办法为 powershell 指定带有嵌入引号的 exec 字符串?由于必须用引号括住多字命令,因此情况变得复杂,而且我找不到转义嵌入引号的方法。我尝试使用以下参数来 Match ... Exec:

# This gives error ${CMDVAR} is not recognized
"powershell -command ${CMDVAR}"

# This executes the script but hangs at script exit
"powershell myscript.ps1"

# This simply hangs
"powershell -command 'my long script with ^"embedded^" quotes"  

这里的目标是执行这个嵌套的 powershell 单行

if ((wmic process where "ProcessID = $((Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId)" get commandline /value| measure-object -Word).Words -gt 2) { exit 1 }

答案1

思考如果没有外部脚本文件这是不可能的。

首先要意识到的是,在 OpenSSH 中,为 指定的命令Match Exec需要用双引号括起来(在配置文件中),因为为 的参数Exec使用以下方式匹配strdelim

readconf.c::match_cfg_line

        /* All other criteria require an argument */
        if ((arg = strdelim(&cp)) == NULL ||
            *arg == '\0' || *arg == '#') {
            error("Missing Match criteria for %s", attrib);
            result = -1;
            goto out;
        }

并且strdelim仅接受双引号作为分隔符:

misc.c::strdelim_internal

#define QUOTE   "\""

/* return next token in configuration line */
static char *
strdelim_internal(char **s, int split_equals)
{
    char *old;
    int wspace = 0;

    if (*s == NULL)
        return NULL;

    old = *s;

    *s = strpbrk(*s,
        split_equals ? WHITESPACE QUOTE "=" : WHITESPACE QUOTE);
    if (*s == NULL)
        return (old);

    if (*s[0] == '\"') {
        memmove(*s, *s + 1, strlen(*s)); /* move nul too */
        /* Find matching quote */
        if ((*s = strpbrk(*s, QUOTE)) == NULL) {
            return (NULL);      /* no matching quote */
        } else {
            *s[0] = '\0';
            *s += strspn(*s + 1, WHITESPACE) + 1;
            return (old);
        }
    }
// ...

所以,只能使用双引号来分隔命令

然后,要意识到的第二件事是,在 Windows 的 OpenSSH 中,指令中使用的命令Exec是使用以下命令执行的system

readconf.c::execute_in_shell

/*
 * Execute a command in a shell.
 * Return its exit status or -1 on abnormal exit.
 */
static int
execute_in_shell(const char *cmd)
{
    char *shell;
    pid_t pid;
    int status;

#ifdef WINDOWS
    return system(cmd);
#else

因此它被执行在cmd.exe(见https://learn.microsoft.com/en-us/cpp/c-language/system-function?view=msvc-170)。 在cmd.exe您需要使用双引号来括住参数,单引号没有特殊含义。

问题是 OpenSSH 中没有办法转义内部双引号。


回到你的例子:

# This gives error ${CMDVAR} is not recognized
"powershell -command ${CMDVAR}"

此处不清楚 中是什么CMDVAR,并且如上所述,您需要在 周围使用转义双引号${CMDVAR},而这目前在 OpenSSH 中是不可能的。

# This executes the script but hangs at script exit
"powershell myscript.ps1"

也许这可以有用"powershell -File myscript.ps1"

# This simply hangs
"powershell -command 'my long script with ^"embedded^" quotes"  

正如所提到的,cmd.exe 需要双引号,因此参数-command需要用转义的双引号括起来,而这目前在 OpenSSH 中是无法实现的。

相关内容