Обработка имен с пробелами

Мой агент Puppet — Windows Server 2012. Я пытаюсь предоставить права db пользователю AD. Если я попытаюсь назначить права пользователю AD, имя которого не содержит пробелов, то скрипт работает нормально. Ранее имя пользователя без пробела также не работало, но когда я добавил дополнительную косую черту ('abc\\s_sql'), оно сработало для этого пользователя. Для имени пользователя с пробелом он вообще не работает, хотя Puppet показывает, что он успешно запущен.

[root@pe-server] cat grant_read.pp
define db::grant_read (
    $grant_read_params
) {
    $grant_read_ps = $grant_read_params[grant_read_ps]
    $grant_read_sql = $grant_read_params[grant_read_sql]
    $read_user = $grant_read_params[read_user]
    $db_name = $grant_read_params[db_name]

    utils::powershell_script { "Grant read access to user $read_user on $db_name":
        script    => $grant_read_ps,
        parameter => "$grant_read_sql $read_user $db_name",
    }
}


[root@pe-server] cat site.pp
node 'pe-agent.abc.com' {
    $grant_read_params_Support_PROD = {
        'grant_read_ps'  => 'c:/db/grant_read.ps1',
        'grant_read_sql' => 'c:/db/grant_read.sql',
        #'read_user'     => 'abc\\s_sql',
        'read_user'      => 'abc\\APP Support_PROD',
        'db_name'        => 'ABC_MASTER',
    }

    db::grant_read { "Granting read access to tom on some db":
        grant_read_params => $grant_read_params_Support_PROD
    }
}


[root@pe-server] cat powershell_script.pp
define utils::powershell_script (String $script, String $parameter = '') {
    $powershell = 'C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -NoProfile -NoLogo -NonInteractive'
    exec { "Running $script on agent with parameter $parameter":
            command => "$powershell -File $script $parameter",
            logoutput => 'on_failure',
            timeout   => 900,
    }
}

Пробовал несколько перестановок и комбинаций как в аргументе файла site.pp, так и в файле grant_read.pp, но, похоже, ничего не работает.

Любая идея, как я могу справиться с этим?


person Technext    schedule 14.03.2017    source источник
comment
Вы пытались изменить одинарные кавычки (' ') на двойные кавычки ()   -  person Will Webb    schedule 14.03.2017
comment
Вероятно, вам нужно добавить вложенные двойные кавычки вокруг параметра: parameter => "$grant_read_sql \"$read_user\" $db_name",   -  person Ansgar Wiechers    schedule 14.03.2017
comment
@WillWebb: я пробовал это раньше, но это не сработало. @AnsgarWiechers: Большое спасибо! Это работает. :) Очень неприятно иметь дело с косой чертой. Ранее я пробовал использовать одинарные кавычки вокруг $read_user, предполагая, что переменная будет передана в utils::powershell_script как есть без интерполяции здесь. Не могли бы вы объяснить или указать какой-нибудь ресурс, который может быть полезен для понимания поведения косой черты в таких случаях? Я буду очень признателен, если вы опубликуете приведенный выше комментарий в качестве ответа (и, если возможно, какую-нибудь справочную ссылку или небольшое объяснение, почему сработала двойная кавычка). Спасибо   -  person Technext    schedule 14.03.2017


Ответы (1)


Вам нужно поставить двойные кавычки вокруг параметра с пробелами. Одинарные кавычки здесь не работают, потому что они недопустимы для кавычек в среде Windows, которая выполняет командную строку PowerShell. И поскольку вы не можете использовать строку в одинарных кавычках (чтобы Puppet не расширял переменные), вы должны избегать вложенных двойных кавычек с помощью обратной косой черты (для Puppet).

В основном это:

"$grant_read_sql \"$read_user\" $db_name"

становится такой строкой:

'c:/db/grant_read.sql "abc\APP Support_PROD" ABC_MASTER'

и, наконец, при вставке в командную строку PowerShell, например:

C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -NoProfile -NoLogo -NonInteractive -File c:/db/grant_read.ps1 c:/db/grant_read.sql "abc\APP Support_PROD" ABC_MASTER

Полностью развернутая командная строка (см. выше) должна быть в форме, позволяющей запускать ее непосредственно из CMD или диалогового окна Выполнить. Это означает, что если какой-либо другой токен (например, путь к скрипту) содержит пробелы, этот токен также должен быть заключен в двойные кавычки.

Итог: вам нужны двойные кавычки вокруг параметра для выполнения командной строки Windows и обратная косая черта, чтобы избежать вложенных двойных кавычек внутри строк в двойных кавычках для Puppet.

person Ansgar Wiechers    schedule 14.03.2017
comment
В дополнение к тому, что сказал Ансгар, я бы также рекомендовал использовать модуль powershell, так как он имеет гораздо более надежную регистрацию для команд powershell, выполняемых в Puppet: forge.puppet.com/puppetlabs/powershell - person Peter Souter; 15.03.2017
comment
Большое спасибо за хорошее и понятное объяснение @Ansgar! Сегодня я наткнулся на еще один случай, когда два параметра имели значения с пробелами, и ваше предложение сработало. :) Спасибо еще раз! - person Technext; 15.03.2017
comment
@PeterSouter: Спасибо за предложение. Раньше я использовал поставщика powershell для всех исполнителей, пока не столкнулся с этим вопрос. Если есть способ справиться с этим, я буду рад попробовать его. Я использую второй блок кода, предложенный @Ansgar в этой ссылке. Это отлично работает для меня. Однако я сталкиваюсь с проблемой при таком подходе в сценариях, где скрипту требуются параметры (как показано в посте выше). В таких случаях я не уверен, как правильно применить блок exit (1 - [int]$?). - person Technext; 15.03.2017