Назад | Перейти на главную страницу

Как совместить две петли foreach?

Я рассмотрел, как объединить несколько команд с помощью psexec, но ни один из методов не работает. Может это потому, что я запускаю скрипт в PowerShell, а не в cmd.exe?

Мне нужно создать учетные записи пользователей и добавить их в локальную группу администраторов на компьютерах, не принадлежащих к домену (Windows 2003). Я получил следующий сценарий (который работает), но мне интересно, есть ли простой способ объединить два цикла foreach, поскольку он должен устанавливать соединение psexec дважды для каждого сервера.

$username = Read-Host "User name:"
$password = Read-Host "Password:"
$fullname = Read-Host "Full name:"
$computers = Get-Content C:\Tools\scripts\ServerList.txt

foreach ($computer in $computers) {
    psexec \\$computer -u username -p password net user $username $password /add /fullname:""$fullname"" /comment:"Comment"
}

foreach ($computer in $computers) {
    psexec \\$computer -u username -p password net localgroup Administrators $username /add
}

Как я уже упоминал, это выполняется в PowerShell. Серверы, на которых я его использую, - это серверы Windows 2003 Workgroup без установленной оболочки PowerShell.

Как сказал @CIA, вы можете объединить циклы, просто запустив psexec дважды в одну петлю.

$username = Read-Host "User name:"
$password = Read-Host "Password:"
$fullname = Read-Host "Full name:"
$computers = Get-Content C:\Tools\scripts\ServerList.txt

foreach ($computer in $computers) {
    psexec \\$computer -u username -p password net user $username $password /add /fullname:""$fullname"" /comment:"Comment"
    psexec \\$computer -u username -p password net localgroup Administrators     
}

Но похоже, что вы действительно спрашиваете, как запустить оба сетевые команды в единственном psexec сеанс.

$username = Read-Host "User name:"
$password = Read-Host "Password:"
$fullname = Read-Host "Full name:"
$computers = Get-Content C:\Tools\scripts\ServerList.txt

foreach ($computer in $computers) {
    psexec \\$computer -u username -p password net user $username $password ullname"" /comment:"Comment" ^&^& net localgroup Administrators     
}

Вы можете попробовать и так, но я не уверен, что это сработает. В && экранируется с помощью ^ так что он передается psexec вместо локальной интерпретации, которая затем запустила бы второй net команда локально.

Альтернатива

Вместо этого вы могли бы не использовать psexec вообще и использовать удаленное взаимодействие PowerShell. Его просто нужно включить на каждой машине, к которой вы хотите подключиться. Я понимаю, что это может оказаться непростым делом, но оно того стоит, поскольку оно более универсально и, по сути, за ним будущее.

Если вы находитесь в домене, вы можете даже использовать групповую политику для включения удаленного взаимодействия PowerShell (полное раскрытие: это моя статья).

Если бы вы это сделали, ваш код выглядел бы так:

$username = Read-Host "User name:"
$password = Read-Host "Password:"
$fullname = Read-Host "Full name:"
$computers = Get-Content C:\Tools\scripts\ServerList.txt

foreach ($computer in $computers) {
    Invoke-Command -ComputerName $computer -ArgumentList $username,$password,$fullname -ScriptBlock { param($u,$p,$f)
        # Everything in here is executed on the remote computer
        net user $u $p /add /fullname:""$f"" /comment:"Comment"
        net localgroup Administrators     
    }
}