Transcript
Page 1: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

PowerShell で One-Get & Chocolateyパッケージを作るときに気を付ける 10 のこと第 3 回 PowerShell 勉強会 2014/07/12@oota_ken

Page 2: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

アジェンダ OneGet と Chocolatey とは? Chocolatey のパッケージの作り方 Chocolatey パッケージを作るときの 10 の地雷

Page 3: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

OneGet と Chocolatey とは? OneGet Windows Management Framework 5.0( 現在は Preview) から追加される Microsoft 謹製のパッケージマネー

ジャー apt-get や yum, Homebrew のようなもの Store アプリではなく、既存のネイティブアプリが対象 但し、ソースからではなく、バイナリでインストール、アンインストール プラグインを追加することで複数のリポジトリをサポート 但し、現状は後述の Chocolatey のリポジトリのみ Chocolatey OneGet 以前に有志により開発されたオープンなパッケージマネージャー インストール済みのものをインストールしないなど「冪等性」については、 Chocolatey が担保してくれます 開発者登録すれば自由にパッケージをアップできます 故に、品質やサポートが玉石混淆です とはいえ、ブラウザからコマンド、開発ツールまで一通り揃っています c inst chrome firefox jdk8 git poshgit gradle intellijidea-community jenkins vim nodejs ruby

Page 4: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

OneGet と Chocolatey のインストール OneGet Windows Management Framework 5.0 Preview May 2014 http://www.microsoft.com/en-us/download/details.aspx?id=42936 コントロール パネル \ すべてのコントロール パネル項目 \ 言語 "English" にしないとインストールがこけます Chocolatey Windows PowerShell – 管理者として実行 Set-ExecutionPolicy Unrestricted iex ((new-object

net.webclient).DownloadString('https://chocolatey.org/install.ps1'))

Page 5: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

Chocolatey パッケージの作り方

Page 6: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

Chocolatey アカウントの作成 アカウント情報の登録 https://chocolatey.org/account/Register

API キーの取得 https://chocolatey.org/account

API キーの登録 nuget.exe setApiKey 上記 URL から取得した API キー -Source

http://chocolatey.org/

Page 7: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

ひな形の取得とコピー cinst warmup git nuget.commandline

cd %ChocolateyInstall%

git clone [[https://github.com/chocolatey/chocolateytemplates.git]]

cd chocolateytemplates\\\_templates

warmup addTemplateFolder chocolatey "%CD%\chocolatey"

warmup chocolatey jdk8

Page 8: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

最低限記述が必要なファイル インストールのみ パッケージ名 .nuspec tools/chocolateyInstall.ps1

アンインストールもサポート 上記に加えて、 tools/chocolateyUninstall.ps1

Page 9: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

パッケージ定義<?xml version="1.0"?><package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>jdk8</id> <title>Java SE 8u5 </title> <version>8.0.5</version> <authors>Sun Microsystems/Oracle Corporation</authors> <owners>oota_ken</owners> <summary>The Java Development Kit (JDK) version 8.0.5</summary> <description>The Java Development Kit (JDK) version 8.0.5</description> <projectUrl>http://www.oracle.com/technetwork/java/javase/downloads/index.html</projectUrl> <tags>java jdk</tags> <licenseUrl>http://www.oracle.com/technetwork/java/javase/terms/license/index.html</licenseUrl> <requireLicenseAcceptance>false</requireLicenseAcceptance> <iconUrl>https://raw.githubusercontent.com/carolynvs/chocolatey-packages/master/Java.JDK/java-logo.jpg</iconUrl> </metadata> <files> <file src="tools\**" target="tools" /> </files></package>

Page 10: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

依存関係の定義*.nuspec に下記のように依存関係を定義すると、 apt や brew のように最初のパッケージを指定してあげるだけで、芋づる式にパッケージがインストールされます但し、バージョン番号とか細かい制御はできないようです <dependencies> <dependency id='gradle' /> <dependency id='maven' /> <dependency id='ant' /> </dependencies>

Page 11: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

tools/chocolateyInstall.ps1 サイレントインストール対応のアプリケーションだと実質 1 行で済みます 例えば、 JetBrains IntelliJ IDEA - Community Edition $name = "intellijidea-community" $url = "http://download.jetbrains.com/idea/ideaIC-13.1.2.exe" $kind = "EXE" $silent = "/S" Install-ChocolateyPackage $name $kind $silent $url

Page 12: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

tools/chocolateyUninstall.ps1 現状の殆どのパッケージでは実装されていません 理由 https://github.com/chocolatey/chocolatey/wiki/CommandsUninstall There are no functions defined in the chocolatey powershell module that would help

with uninstall Chocolatey 側ではアンインストールには最小限のコマンドレット or 関数しか用意されてい

ません パッケージ毎に個別に実装する必要があります jdk8 例 ( 抜粋 ) $jdk = "/qn /x {64A3A4F4-B792-11D6-A78A-00B0D0" + $uninstall_id + "0}" Start-ChocolateyProcessAsAdmin $jdk 'msiexec' $java_bin = get-java-bin Uninstall-ChocolateyPath $java_bin 'Machine'

Page 13: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

パッケージ化と検証、発行 パッケージ化 cpack

ローカルインストールで検証 cinst jdk8 -source '%cd%'

( アンインストールをサポートしている場合 ) ローカルアンインストールで検証

cuninst jdk8

パッケージを発行する cpush jdk8.1.8.0.05.nupkg

Page 14: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

Chocolatey パッケージを作るときの 10の地雷

Page 15: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

*.nuspec での ID とバージョン番号 <id>jdk8</id>

<title>Java SE 8u5 </title>

<version>8.0.5</version>

PowerShell ではありませんが・・・ id 基本的に自由につけられます が、同じようなものが乱立しており、

もめてます java.jdk, jdk7, jdk, jdk8

version JDK, JRE 内で統一の動きがあります パッケージ自体のマイナーバージョ

ンアップに統一見解がないです 8.0.501 とか?

Page 16: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

直ダウンロードインストールが簡単にできない場合 [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

$client = New-Object Net.WebClient

$client.Headers.Add('Cookie', 'gpw_e24=http://www.oracle.com; oraclelicense=accept-securebackup-cookie')

$client.DownloadFile($url, $output_filename)

提供元の Web サイトを解析して、認証やクッキーの設定をした上で、ローカルにダウンロードする必要があります

提供元の Web サイトの仕様変更があっても、文句は言えず、仕様変更に追従する必要があります

ライセンス上 OK なのか怪しいところもあります

Page 17: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

副作用のある関数やコマンドレットを呼び出している場合 >function add($a, $b) { return $a + $b; }

> function call_add { add 1 2; add 2 3; return 6 }

C:\Users\KenichiroOta> call_add

3

5

6

嵌まった場所 $dummy =

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

$client = New-Object Net.WebClient 以下略

PowerShell では、 return 文以外でも、値はすべて関数の結果として返されます

結果ではなく副作用の動作を期待して、関数やコマンドレットを呼んでいる場合に忘れがちです

対応 メソッド:呼び出し [void] で打ち消します コマンドレット: $dummy とかに代入します 嵌まった場所 [System.Net.ServicePointManager]::ServerCerti

ficateValidationCallback = { $true } 実はこの代入文の戻り値はコールバックのスクリプ

トブロックですので下記のような修正が必要です $dummy =

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

Page 18: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

アンインストールサポートの欠如 $use64bit = use64bit

if ($use64bit) { $jdk = "/qn /x {64A3A4F4-B792-11D6-A78A-

00B0D0" + $uninstall_id + "0}" $jre = "/qn /x {26A24AE4-039D-4CA4-87B4-

2F864" + $uninstall_id + "FF}"

} else { $jdk = "/qn /x {32A3A4F4-B792-11D6-A78A-

00B0D0" + $uninstall_id + "0}" $jre = "/qn /x {26A24AE4-039D-4CA4-87B4-

2F832" + $uninstall_id + "FF}"

}

Start-ChocolateyProcessAsAdmin $jdk 'msiexec'

Start-ChocolateyProcessAsAdmin $jre 'msiexec'

アンインストールに関するヘルパーが殆どありません

https://github.com/chocolatey/chocolatey/wiki/CommandsUninstall

サポートしている Helper Uninstall-ChocolateyPackage UnInstall-ChocolateyZipPackage

サイレントアンインストールはソフトウェアによってバラバラです

殆どのパッケージでアンインストールをサポートしていません

→上記よりアンインストールの実装のノウハウが不足しています

Page 19: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

環境変数の取り扱い Install-ChocolateyPath $java_bin 'Machine'

内部実装 [Environment]::SetEnvironmentVariabl

e('Path', $actualPath, $pathType)

Install-ChocolateyEnvironmentVariable 'JAVA_HOME' $java_home 'Machine'

$env:Path = $actualPath

環境変数の変更が反映されてない ??

cinst でインストールして、環境変数を書き換えたのに、元のシェル ( コマンドプロンプト、 PowerShell) 上では環境変数の変更が反映されていません

cinst は新たに PowerShell を起動して、その中で SetEnvironmentVariable しています

従って、親のシェルには反映されません 親のシェルはそのシェルの起動時に環境変数を親プ

ロセスからコピーするため、 cinst 後、再度GetEnvironmentVraible しても、更新後の環境変数の値が取得できません

→現実にはレアケースですが、同じシェルのまま、 cinst, cuninst すると環境変数の残骸が残るという面倒なことが起きます

分かりにくいので次ページの図で

Page 20: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

環境変数の取り扱いステップ Windows本体

cinstを起動したシェル

cinst内部のPowerShell

cuninst内部のPowerShell

cinst後起動したシェル

cinst 前

cinst 後 key=value key=value

シェルもう一つ起動 key=value key=value

cuninst を起動 key=value

ない!! (cinst を起動したシェルを引き継ぐ ) key=value

cunsint 後 key=value (残骸として残る )

※このシェルでcuninst を起動すれば問題ない

※このシェルでcuninst を起動すれば問題ない

Page 21: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

x64, x86 の判断 function use64bit() {

$is64bitOS = (Get-WmiObject –Class Win32_ComputerSystem).SystemType -match ‘(x64)’

return $is64bitOS

}

if ($use64bit) { $jdk = "/qn /x {64A3A4F4-B792-11D6-

A78A-00B0D0" + $uninstall_id + "0}" $jre = "/qn /x {26A24AE4-039D-4CA4-

87B4-2F864" + $uninstall_id + "FF}"

} else { # 略 }

アプリケーションが x64版、 x86版の方を用意している場合、オプションインストールのサポートを含めると、最悪以下の組合せ毎にロジックを書く必要があります

x64 OS に x86 アプリケーションを入れた先と x86 OS に x86アプリケーションを入れた先が異なるのがロジックミスをしやすく要注意です

OS アプリケーション 標準インストール先x64 x64 C:\Program Files

x64 x86 C:\Program Files (x86)

x86 x86 C:\Program Files

Page 22: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

OneGet でのテスト Chocolatey cinst jdk8 -source '%cd%'

OneGet cpush jdk8.1.8.0.05.nupkg Install-Package jdk8 Uninstall-Package jdk8

OneGet ではローカルインストール検証のサポートは現状ありません

Chocolatey でローカル検証した後、本番アップして検証する綱渡りです

後述しますが、 OneGet では各コマンドはネイティブ実装 (DLL) されています

Chocolatey のパッケージ・プロバイダーもDLL で実装されており、 PowerShell で実装されているオリジナルの Chocolatey の挙動と微妙に異なるところがあり、検証は必須です

OneGet で正常に動作しないと、その間の本番パッケージは OneGet でインストールできない状態になるので注意が必要です

正式版の OneGet の改善を望みます

Page 23: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

x64, x86 * Chocolatey, OneGetのテスト Chocolatey * x64, x86 cinst jdk8 –source '%cd%' cunint jdk8

OneGet cpush jdk8.1.8.0.05.nupkg Install-Package jdk8 Uninstall-Package jdk8

下記の組合せテストが必要ですOS Chocolat

eyOneGet

アプリ

x64 Chocolatey

x64

x86

OneGet x64

x86

x86 Chocolatey

x86

OneGet x86

Page 24: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

開発効率のための管理者として実行 function Start-ChocolateyProcessAsAdmin {

# 略 $psi = new-object

System.Diagnostics.ProcessStartInfo; $psi.FileName = $exeToRun;

if ([Environment]::OSVersion.Version -ge (new-object 'Version' 6,0)){

$psi.Verb = "runas"; } # 略}

Start-ChocolateyProcessAsAdmin

内部で runas しています Start-ChocolateyProcessAsAdmin を

呼び出している functionごとに、以下のダイアログがでます

ユーザーアカウント制御 次のプログラムにこのコンピュータへの変

更を許可しますか? →ダイアログボックスを手動で "OK" す

る必要があり、開発効率が悪いです →親プロセスの PowerShell を「管理者

として実行する」で起動して回避します →これで効率化すると次の地雷が・・・

Page 25: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

最終実行は通常実行 function Start-ChocolateyProcessAsAdmin {

param(

[string] $statements,

[string] $exeToRun = 'powershell',

[switch] $minimized,

[switch] $noSleep,

$validExitCodes = @(0)

) # 略 if ($minimized) { $psi.WindowStyle =

[System.Diagnostics.ProcessWindowStyle]::Minimized;

} # 略}

Start-ChocolateyProcessAsAdmin not 「管理者として実行」 かつ $minimized = $true で呼び出さないと 呼び出す度にサブウィンドウが開きます 難解も開くのがウザいので間違って閉じてしまう可能性が

あります というか、じぶんでやってしまいました そうすると、サブプロセスがエラー Exit でインストールが

失敗します ユーザーがやってしまいがちです 対処方法 $minimized = $true で呼びます ・・・が、 function Install-ChocolateyPath { # 略 Start-ChocolateyProcessAsAdmin "$psArgs" # 略 Chocolatey の関数自体が minimzed = $true してません

Page 26: PowerShellでOneGet & Chocolateyパッケージを作るときに気を付ける10のこと

まとめ OneGet & Chocolatey ネイティブアプリの一括インストールは劇的に楽になりました ただし、アンインストールのサポートが殆ど無いです OneGet の今後の整備に期待します OneGet & Chocolatey のパッケージ作り OS x アプリ x (OneGet | Chocolatey) の組合せテストが大変です もうちょっと、アンインストール系を始め API が充実して欲しいです とはいえ、色々整備されると嬉しいのでみんな作ってみましょう (震え声 )


Top Related