LoginSignup
17
19

More than 5 years have passed since last update.

JenkinsでPowerShellを使う際の注意事項

Last updated at Posted at 2016-02-07

JenkinsでPowerShellを使う際の注意事項

Windows PowerShell、慣れると便利なんですけど、バージョンアップのたびに前提が変わったりするので、複数の環境が混在していたりするとハマります。
ネットで検索しても、バージョンによって異なる情報が出てきて混乱するし。
あと、ドメイン環境と非ドメイン環境、Jenkinsとかサービスから実行する場合などでも動作が変わるので注意が必要です。
(基本的には実行ユーザの問題と、マシン間の信頼関係の問題なんですが、未だに理解しきれません。間違ってるところあればコメント願います。。。)

ここでは、JenkinsからPowerShellで複数のマシンをコントロールする際にハマりやすいところを中心にメモしておきます。
なお、以降でJenkins側と言ってるのはあくまでPowerShellを実行するマシンのことです。Jenkins Slave使って更に他のマシンからPowerShellを実行する場合は、そこがJenkins側にあたることになります。

なお、以降PoweShellの設定を行うコマンドは、基本的に全て管理者権限のある状態で実行する必要があります。

ソフト等 バージョン 備考
Windows Server 2012R2
PowerShell v4.0 2012R2標準
Jenkins v1.647
PowerShell plugin v1.3

リモート側は以下の通り。

ソフト等 バージョン 備考
Windows 10
PowerShell v5.0 Windows10標準

Jenkins側の設定

PowerShell plugin

何は無くとも、PowerShell pluginを入れます。
ネットにつながっていれば、プラグインマネージャーからチェックしてインストール。
つながってなければ、つながっているマシンで(archives) とかから辿って、powershell.hpiファイルを入手してください。
プラグインマネージャの高度な設定から、プラグインのアップロードでインストールします。

Jenkinsサービスのユーザ変更

Windowsのサービスから「Jenkins」のプロパティを表示すると、ログオンタブにJenkinsサービスを実行するユーザが設定されていますが、デフォルトではマシンのローカルシステムアカウントなどになっていると思います。
これでもPowerShellを実行することはできますが、他のマシンでのリモート実行を行うことが出来ません。
リモート実行を行う場合は、必要に応じて「Administrator」などのアカウントを設定します。(要Jenkinsサービスの再起動)
なお、ドメイン環境ならぜひAdministrator権限を持つドメインユーザの設定をお勧めします。リモート接続が簡単になります。


Jenkins側(リモート操作する側)と、操作される側に共通の設定

PowerShell実行ポリシー

PowerShellのスクリプトファイル(.ps1ファイル)の実行は、PowerShellのバージョンによってデフォルトの実行ポリシーが違うので、そのままでは動かない場合があります。(まだ動かない環境の方が多いでしょう。)
PowerShellを実行し、次のコマンドで確認できます。(意味はこことか参照)

Get-ExecutionPolicy

Windows Server 2012(PowerShell v4.0)以降などは、初めから「RemoteSigned」なので変更不要ですが、「Restricted」などの場合は次のようなコマンドを入力し適切な設定が必要です。

Set-ExecutionPolicy RemoteSigned


Jenkins側(リモート操作する側)の設定

WinRmサービスの構成

WinRm(リモート管理サービス)は、細かい違いが多くて自分の中でも整理できていませんが、とりあえず次のコマンドで普通は設定できます。(プロンプトは全部「y」で大丈夫)

WinRm QuickConfig

信頼できるマシンの設定

非ドメイン環境では、事前にリモート接続する相手のマシンを登録しておく必要があります。
(ドメイン環境ならやる必要なし。初めての非ドメイン環境は、これでハマった)

Set-Item WSMan:\localhost\Client\TrustedHosts <相手マシン名>

(相手マシンが多いとか、安全な環境なら、<相手マシン名>は「*」でもOK。)


操作される側の設定

リモート接続の構成

次のコマンドで、ポートとかのリモート接続の受け側の設定が行われます。
(これにはWinRmサービスの構成も含まれています。)

Enable-PSRemoting

リモート接続するユーザの設定

Jenkinsを実行しているユーザと同じ、またはAdministrator権限を持つユーザが有効になっている必要があります。
ドメイン環境なら何もせずとも問題ない場合が多いのですが、非ドメイン環境の場合、特にAdministratorがデフォルトで無効になっているクライアントOS(Windows10とか)の場合、注意が必要です。
一番無難なのは、JenkinsをAdministratorで動かし、操作される側もAdministratorを有効にした状態です。

admin.png


Jenkinsからリモートでコマンドを実行してみる

Jenkinsでビルドを作り、ビルド手順の追加で「Windows PowerShell」を選択し、以下のソースを貼り付けます。

 PowerShellソース

リモートでコマンドを実行する先のマシン名は、初めに配列で記述してあります。
なお、リモート側で実行するコマンドの中身は、PowerShellからMongoDBにアクセスする。と同じものなのでそちらを参考にしてください。

##### 指定マシンの情報をリモートジョブで取得 #####

# 対象のマシン名
$REMOTE = @( 'V1', 'V2', 'V3' );

# 開始日時を表示
$date = Get-Date;
"##### $date #####";

# 対象のマシンで同時に(AsJob)ジョブ実行
ForEach($computername in $REMOTE) {
  Invoke-Command -ComputerName $computername -AsJob -ScriptBlock {
    @{
      "Processor_per" = [int](Get-Counter -Counter "\Processor(_Total)\% Processor Time").CounterSamples.CookedValue;
      "Network_byte" = [int]((Get-Counter -Counter "\Network Interface(*)\Bytes Total/sec").CounterSamples.CookedValue | Measure-Object -Maximum).Maximum;
      "Disk_byte" = [int](Get-Counter -Counter "\LogicalDisk(_Total)\Disk Bytes/sec").CounterSamples.CookedValue;
    }
  }
};

# ジョブが無くなるまで繰り返し
While((Get-Job) -ne $null) {
  # 1秒待ち、日時とジョブの状況を表示
  Start-Sleep -Second 1;
  $date = Get-Date;
  "##### $date #####";
  Get-Job;

  # 完了(Completed)したジョブを全て受け取り、削除
  ForEach($job in (Get-job -State "Completed")) {
    # 完了したジョブの見出しを表示
    $Id = $job.Id;
    $Location = $job.Location;
    "##### Id = $Id / Location = $Location #####";

    # 結果をjsonで表示し、ジョブを削除
    Receive-job -Id $Id | ConvertTo-json;
    Remove-job -Id $Id;
  };
};

ここでは、Invoke-Commandに-AsJobを指定して、最初の配列に定義した、V1,V2,V3の3台のマシンに同時にジョブを実行させています。
なお、ForEach(\$a in \$b) {\$a}は、\$b.ForEach({\$_})と書きたいのですが、(Get-job -State "Completed").ForEach()したところで該当のジョブが1つしかないとエラーとなってしまったので、この書き方にしています。
(たぶんPowerShellが、Jenkins側のV4.0と、リモート側のv5.0で違う影響かと思いますが、詳細不明。。。)

実行結果

このビルドを実行したところ、次のような結果となりました。

ユーザーanonymousが実行
ビルドします。 ワークスペース: C:\Jenkins\workspace\VM_Loggong
[VM_Loggong] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\Users\ADMINI~1\AppData\Local\Temp\hudson2286994124897927906.ps1'"
##### 02/07/2016 11:25:13 #####

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
--     ----            -------------   -----         -----------     --------             -------                  
1      Job1            RemoteJob       Running       True            V1                   ...                      
3      Job3            RemoteJob       Running       True            V2                   ...                      
5      Job5            RemoteJob       Running       True            V3                   ...                      
##### 02/07/2016 11:25:14 #####
1      Job1            RemoteJob       Running       True            V1                   ...                      
3      Job3            RemoteJob       Running       True            V2                   ...                      
5      Job5            RemoteJob       Running       True            V3                   ...                      
##### 02/07/2016 11:25:15 #####
1      Job1            RemoteJob       Running       True            V1                   ...                      
3      Job3            RemoteJob       Running       True            V2                   ...                      
5      Job5            RemoteJob       Running       True            V3                   ...                      
##### 02/07/2016 11:25:16 #####
1      Job1            RemoteJob       Running       True            V1                   ...                      
3      Job3            RemoteJob       Running       True            V2                   ...                      
5      Job5            RemoteJob       Running       True            V3                   ...                      
##### 02/07/2016 11:25:17 #####
1      Job1            RemoteJob       Running       True            V1                   ...                      
3      Job3            RemoteJob       Running       True            V2                   ...                      
5      Job5            RemoteJob       Running       True            V3                   ...                      
##### 02/07/2016 11:25:18 #####
1      Job1            RemoteJob       Running       True            V1                   ...                      
3      Job3            RemoteJob       Completed     True            V2                   ...                      
5      Job5            RemoteJob       Completed     True            V3                   ...                      
##### Id = 3 / Location = V2 #####
{
    "Disk_byte":  40930,
    "Network_byte":  41749,
    "Processor_per":  45,
    "PSComputerName":  "V2",
    "RunspaceId":  "ccf5b5e1-e871-4751-8b00-5484f71e960f",
    "PSShowComputerName":  true
}
##### Id = 5 / Location = V3 #####
{
    "Disk_byte":  0,
    "Network_byte":  60,
    "Processor_per":  0,
    "PSComputerName":  "V3",
    "RunspaceId":  "ebd12ad4-f4d2-48e6-aa21-f6b81cd28aaf",
    "PSShowComputerName":  true
}
##### 02/07/2016 11:25:19 #####
1      Job1            RemoteJob       Completed     True            V1                   ...                      
##### Id = 1 / Location = V1 #####
{
    "Disk_byte":  0,
    "Network_byte":  520745,
    "Processor_per":  25,
    "PSComputerName":  "V1",
    "RunspaceId":  "96a08f24-1f44-4cf8-b1e0-ceb1ecceb90b",
    "PSShowComputerName":  true
}


Finished: SUCCESS

V1,V2,V3のジョブが同時に投入され、V2とV3は5秒後に、V1が6秒後に終わりました。
-AsJobで同時に実行しないとすれば、6+5+5で16秒かかる処理が、6秒で終わりました。
リモートでコマンドを実行するマシンが増えるにつれ、-AsJobの効果が大きくなります。

17
19
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
19