質問: 知りたいこと ------ VirtualBox仮想マシン(以下VM)のOSが起動完了したことを検知する方法 --- 状況 -- VirtualBoxでVMを立ち上げて開発等の作業をしています。 今まで作業開始時に、VMの立ち上げ、SSHログイン等を手動で行ってきましたが、自動化できないかと思い、シェルスクリプトにて実現しようとしていますが、一つ壁に当たりました。 **VMのOSが起動完了したタイミングが分からない。** というものです。 SSHで接続するところまで自動化しようとすると、OSが(sshdと言ったほうがいいのでしょうか?)起動完了しているかがわからないとSSHが弾かれます。 Virtualboxで仮想マシンが起動完了したことを確認するコマンドはあるのですが、これはあくまでマシンが立ち上がったことを確認できるものであり、OSが立ち上がったかどうかを確認するものではないようです。 --- 現状での妥協案 シェルスクリプト ---------------- 現状では「**OSが立ち上がってる≒SSHでの接続が可能**」という認識のもと、逆転の発想で「**OSが立ち上がっていない≒SSH接続が弾かれる**」という状況を利用しています。 自分の環境ではVMのOSが起動に大体1分くらいかかるので、まず1分ウエイトしてから、SSH接続が成立するまで繰り返し試行する方法をとるものです。以下は下手で恥ずかしいですが、作成したシェルスクリプトです。 ``` #!/bin/bash white_green="\e[37;42;1m" white_red="\e[37;41;1m" colorEnd="\e[m" #引数確認 if [ $# -eq 0 ]; then /bin/echo -e "${white_red}VM名を指定してください${colorEnd}" exit 1 fi VBoxManage list vms | grep "$1";isvms=$? if [ $isvms -ne 0 ]; then /bin/echo -e "${white_red}指定されたVM名は存在しません${colorEnd}" /bin/echo -e "${white_red}存在するVM名は以下です${colorEnd}" VBoxManage list vms exit 1 fi #起動確認 VBoxManage list runningvms | grep "$1";isRunning=$? if [ $isRunning -eq 0 ]; then /bin/echo -e "${white_red}$1はすでに起動しています${colorEnd}" exit 1 fi #VM起動 VBoxManage startvm "$1" --type headless > /dev/null 2>&1 /bin/echo -e "${white_green}VM起動${colorEnd}" #OSが起動するまでに約1分かかるのでウエイトを挟む e=0 /bin/echo -e "${white_green}OS起動待機中(60秒待ちます)${colorEnd}" for e in 0 5 10 15 20 25 30 35 40 45 50 55 60; do echo -n "$e秒...\r" sleep 5s done #ssh接続 vmname="ssh -p22 -i ~/.ssh/id_rsa hoge@host" count=0 /bin/echo -e "${white_green}ssh接続中...${colorEnd}" until eval ${vmname} do echo -n "..." sleep 5s count=$((count+1)) if [ $count -gt 20 ]; then /bin/echo -e "${white_red}20回試行したがダメでした${colorEnd}" exit 255 fi done exit 0 ``` --- ベストプラクティスは? ----------- 一応目的は果たせているのですが、SSHの接続可否を用いるのはいまいちスマートではないように感じています。 VMのOSが立ち上がったタイミングを取得できる方法をご存知のかたよろしくおねがいします。
回答: 一般論として「OSが起動した」ということをどう定義しましょうか。 - OS Kernel 部がロードされた状況(まだ daemon/service 類は起動していない) - コンソールログインができる状況 - GUI ログインができる状況 - 使いたい daemon/service 類が接続を受け付ける状況 今回の場合、使いたいのは [ssh](/questions/tagged/ssh "'ssh' のタグが付いた質問を表示") なので - [ssh](/questions/tagged/ssh "'ssh' のタグが付いた質問を表示") で接続しようとして、できたら [ssh](/questions/tagged/ssh "'ssh' のタグが付いた質問を表示") 起動済み というのが最適(つまり現状が最適)だと、オイラ個人としては思います。 同様 - [mysql](/questions/tagged/mysql "'mysql' のタグが付いた質問を表示") に接続しようとして、できたら [mysql](/questions/tagged/mysql "'mysql' のタグが付いた質問を表示") 起動済み - [http](/questions/tagged/http "'http' のタグが付いた質問を表示") 接続しようとして、できたら [apache](/questions/tagged/apache "'apache' のタグが付いた質問を表示") 起動済み ってことだと思います ([mysql](/questions/tagged/mysql "'mysql' のタグが付いた質問を表示") や [apache](/questions/tagged/apache "'apache' のタグが付いた質問を表示") が自動起動/手動起動のどっちでも)。 こういうとき、よく `ping` が通ったら・・・という回答を見かけますが `ping` が通ってもそれは単に `ICMP` 起動済みでという意味でしかないのであまり役に立たないっす。 (目的のサービスはまだ実行されていないかもしれない) 使いたいサービスに対して接続できたらOK以上に確実な方法は無いでしょう。