GitHubと連携できるCI/CDサービスでWindows環境も使える AppVeyor でログだけ見ても良くわからないエラーが出たので 実行しているWindowsにリモートデスクトップでログインしてエラーを分析してみました。
AppVeyor
AppVeyor はGitHubと連携できるCI/CDサービスで Windows環境を使えるサービスは少ないのでWindowsを使いたいときはよく使われてました。
(ただ最近はGitHub Actionsが出来てWindowsも使えるのであれかも。)
起こった問題
vim_ahkとかでテストやリリース用のバイナリを コンパイルするのに使ってます。
最近新しいリリースを作ったらバイナリが作られず、ログを見てみると コンパイルしているところで止まっっていました。
具体的には Ahk2Exe というアプリでAutoHotkeyのスクリプトをexeファイルに変換する部分で止まっていました。
止まった状態で最終的にタイムアウト(60分)経って失敗する、という感じ。
このアプリは細かいデバッグログを吐く様な設定が無いし、 手元のWinodwsだと何も問題なく動くのでどうもわからない状態でした。
そこで実際にコンパイルしている環境に入って見てみることに。
リモートデスクトップの設定
AppVeyorでは実行しているWindowsのVMにリモートデスクトップ(RDP)でアクセスすることが出来ます。
Accessing Windows build worker via Remote Desktop (RDP) AppVeyor
上にある通りやればOK。
AppVeyorの設定ファイル.appveyor.ymlで、
init
のセクションに
init:
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
と、リモートデスクトップを有効にする設定を入れます。 これをするとこれ以降の部分でスクリプトを実行している間リモートデスクトップでログイン出来るようになります。
これを設定して実行すると、AppVeyorのウェブから見えるログに、
iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
Remote Desktop connection details:
Server: XX.XXX.XXX.XXX:XXXXX
Username: appveyor
Password: XXXXXXXXXXXXXXX
Build paused. To resume it, open a RDP session to delete 'Delete me to continue build.txt' file on Desktop.
といった表示の状態でAppVeyorのページで見れるログの表示が止まる様になります。
ここにログインに必要なサーバー、ユーザー名(必ずappveyor
)、パスワードの情報が表示されます。
この状態でリモートデスクトップを立ち上げて上の通りに接続してあげれば 実行している環境にログイン出来ます。
パスワードは何も設定してないと毎回自動的に決めて上の様に表示してくれますが、
そのプロジェクトのSettingsEnvironment
からAPPVEYOR_RDP_PASSWORD
という値を決めておくと上のPassword
表示がなくなり、
APPVEYOR_RDP_PASSWORD
がパスワードになります。
または.appveyor.ymlのenvironment
セクションでAPPVEYOR_RDP_PASSWORD
の値を
設定することでも同様になります。
environment:
- APPVEYOR_RDP_PASSWORD: XXXXXXXXXXXXX
ログインしたらWindowsなのでコマンドプロンプトを立ち上げて実行スクリプトを手で 実行してみたり色々試すことが出来ます。
これだと実行スクリプトが一通り終わると立ち上がったVMも終了してしまい、 すぐに終わるスクリプトだとログインする暇も無いですが、 すべて終わった状態で調べたい場合には 代わりに終了時に以下を実行する様に設定:
on_finish:
- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
$blockRdp = $true;
加えることでこれを実行した箇所でスクリプト自体が止まる様になり、
その状態でログイン出来るようになります。
これは別にon_finish
でなくても良くて、
build_script:
- cmd echo test1
- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- cmd echo test2
- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- ...
みたいな感じで止めたいところに複数置くことが出来ます。
$blockRdp = $true;
な状態でログインするとデスクトップに
Delete me to continue build.txtというファイルがあります。
このファイルを消すとブロック状態が終わってスクリプトが先に進んでいきます。
その後に止まるところがなければ全部終了してVMも落ちるので 接続したままでもそのうちサーバー側がなくなって切断します。
init
セクションなどで
$blockRdp = $true
なしでログインした場合にはスクリプトが終わるまでログイン出来る状態になっています。
今回の問題
さて、上の様にしてログインしてみると
みたいなのが出てました。
この
Error: Unable to copy AutoHotkeySC binary file to destination.
でググってみるとこのバイナリが別プロセスで実行中だったりすでにこのファイルがあったり、 だとか言う話が出てきましたが、 調べてみるとC:\Users\appveyor\AppData\Local\Temp\ **には~Ahk2Exe~build**というフォルダすらない状態。
で、どうやら単にC:\Users\appveyor\AppData\Local\Temp~Ahk2Exe~build\vim_ahk~exe~xxxxxxx.tmp というファイルが書き込めない、という状態らしい。
試しにC:\Users\appveyor\AppData\Local\Temp~Ahk2Exe~buildというフォルダを手動で作ってやると コマンドが成功しました。
パーミッションか何かおかしいのかな、と思ってちょっと調べてみます。
C:\Users\appveyor>dir /q C:\Users\appveyor\AppData\Local\Temp
Volume in drive C is Windows
Volume Serial Number is D4AB-4044
Directory of C:\Users\appveyor\AppData\Local\Temp
08/09/2020 08:54 AM <DIR> APPVYR-WIN\appveyor .
08/09/2020 08:54 AM <DIR> APPVYR-WIN\appveyor ..
08/09/2020 08:54 AM <DIR> BUILTIN\Administrators 1
0 File(s) 0 bytes
3 Dir(s) 44,071,612,416 bytes free
C:\Users\appveyor>
ということで、Tempの下に1という管理者が作ったものはありますが、
Temp自体はappveyor
ユーザーのもので特におかしくない模様。
実際、上にも書いてますが、フォルダから手動でも作れましたし、コマンドで、
C:\Users\appveyor>mkdir "C:\Users\appveyor\AppData\Local\Temp\~Ahk2Exe~build"
としても作れました。なのでパーミッションの問題、 というよりはフォルダがない状態でその中に書き込もうとしてるの問題という感じ。
ちょっと色々やってみようと、
SET AHKPath=C:\Program Files\AutoHotkey
"%AHKPath%\compiler\ahk2exe.exe" /in vim.ahk /out build/vim_ahk.exe
というコマンドを
SET AHKPath=C:\Program Files\AutoHotkey
"%AHKPath%\compiler\ahk2exe.exe" /in vim.ahk /out build/vim_ahk.exe /bin "%AHKPath%\compiler\AutoHotkeySC.bin
としてみても特に変わらず(相変わらずAutoHotkeySCをコピーしようとする)。
ahk2exe.exeはそのまま実行するとGUIで使えるので、 GUIを立ち上げて上の入出力ファイルを設定してConvertしてみると C:\Users\appveyor\AppData\Local\Temp~Ahk2Exe~build がなくても成功します。
どうやらコマンドとして実行するときだけ一時ファイルを使う?
試しにローカル環境でTempにファイルが出来るかどうか見てみると、
**C:\Users\user\AppData\Local\Temp\~temp507510843.tmp**
みたいにTemp直下に一時ファイルが出来ていました。 GUIでやると何も出来ず。
手元のWindowsはWindows 10、AppVeyorはWindows Server 2012 R2 Datacenter。 AutoHotkeyは手元が 1.1.31.00、 Appveyorでは最新の1.1.33.2。
まず、Windowsの違いで%TEMP%か%TMP%の値が違うのか、と思ってcmd: echo %TEMP%
とかで見てみると
とちらも
C:\Users\appveyor\AppData\Local\Temp
で特に変わらず。
AutoHotkeyのバージョンも違いますが、関係ないかな、と思いながら手元のAutoHotkeyをアップデートして試してみると、 同じエラーが出ました。。。
どうやらAutoHotkeyのバージョンのせいらしい。
AutoHotkeyの現在のレポジトリは以下。
で、ちゃんと理解してないですが、おそらく上のメインのレポジトリで作られるsetupファイルで、 実際にインストールするときに入れられるAhk2Exeは以下。
これらを見ても上の様な問題がIssueになったりはしてません。
Upcoming Ahk2Exe Changes (2019) - AutoHotkey Community
この辺のところを見ても特になし。
調べてみると1.1.32.00では問題なく、1.1.33.00から問題が起こっている模様。 1.1.33.00が今年の6月に作られたもの。
問題があればIssueとかになってても良さそうなものですが、 そもそもAhk2Exeを使ってバイナリ化する、ということがそれほどないかもしれませんし、 GUIを使う人はあれ、コマンドとして実行する、というのが稀すぎて気づかれてないだけかも?
もうちょっと調べてIssueとかに投げてみます。
追記: 2020/08/10
いくつかの環境で再現したのと、version 1.1.32.00だと出なくて1.1.33.00で出てきたものだということまで確認出来たのでIssueを投げておきました。
Unable to copy error by command line · Issue #68 · AutoHotkey/Ahk2Exe
追記ここまで
追記: 2020/08/10
上のIssueで返事をいただきましたが、問題はvim_ahkのコンパイルのときに、
"%AHKPath%\compiler\ahk2exe.exe" /in vim.ahk /out build/vim_ahk.exe
としていて、最後のexeの出力でパスの区切りに/
を使ってることでした。
v1.33.00の時点で、一時ファイルの作り方を改善したらしく、
出力ファイルの名前も使うようになり、パスをパースするする際に
Windows的なバックスラッシュを使うのでスラッシュがあるとおかしな変換になり、
結果ディレクトリを余計に作る様な状態に陥ってしまっていたようです。
(/
をパスの区切りとしたり、そうでなかったりするWindowsの弊害。。。)
ということで、上のものを
"%AHKPath%\compiler\ahk2exe.exe" /in vim.ahk /out build\vim_ahk.exe
とすれば(最後のbuild/
の部分がbuild\
に)%TEMP%
直下に直接一時ファイルを作るようになり、上記のエラーは出なくなります。
こちらのレポジトリまで見に来てくれてバグを見つけてくれて、 作者の人にはホント感謝(すいません、お騒がせしました)。
追記ここまで
解決法
上にも書いたとおりフォルダが無いのが問題なので、コンパイルを実行する前に %TEMP%の下にディレクトリを作ってやればよいわけですが、 手元の環境でもなるということで、コンパイルするためのスクリプトの中に入れてしまいます。
1 2 3 4 5 |
|
な感じ。
取り敢えずAhk2Exeでfixされるまで。