VirtualBoxのCLIのチートシート

vm一覧

$ VBoxManage list vms

起動してるvm一覧

$ VBoxManage list runningvms

仮想マシンのheadless起動

$ VBoxManage startvm 2274443e-f95e-47ca-af10-33c931ac3883 --type=headless

type指定しなければGUIつきで上がる。

仮想マシンの一時停止

$ VBoxManage controlvm 2274443e-f95e-47ca-af10-33c931ac3883 savestate

VirtualBoxのExtension PackをCLIで更新する

ssh -Y でリモートのサーバーに接続して、 VirtualBox Extension Packを更新したかったのだけど、Virtual Boxの画面からやろうとすると、こんなエラーが出る

The installer failed with exit code 127: Error creating textual authentication agent: Error opening current controlling terminal for the process (`/dev/tty'): No such device or address.

調べてみるとsudoできないので失敗してるらしい。CLIでできないか調べたらできそうだった。

$ VBoxManage extpack uninstall
Oracle VM VirtualBox Command Line Management Interface Version 7.0.2
Copyright (C) 2005-2022 Oracle and/or its affiliates

VBoxManage: error: No extension pack name was given to "extpack uninstall"

Usage:

  VBoxManage extpack uninstall [--force] <name>

名前が必要と。それではということで、extension pack 一覧を取得

$ VBoxManage list extpacks
Extension Packs: 1
Pack no. 0:   Oracle VM VirtualBox Extension Pack
Version:        6.1.34
Revision:       150636
Edition:
Description:    Oracle Cloud Infrastructure integration, USB 2.0 and USB 3.0 Host Controller, Host W
ebcam, VirtualBox RDP, PXE ROM, Disk Encryption, NVMe.
VRDE Module:    VBoxVRDP
Crypto Module:
Usable:         false
Why unusable:   VBoxExtPackRegister returned VERR_VERSION_MISMATCH, pReg=0000000000000000 ErrInfo='H
elper version mismatch - expected 0x30000 got 0x50000'

なるほど。で、名前ってどれ?

$ VBoxManage uninstall extpack 6.1.34
Oracle VM VirtualBox Command Line Management Interface Version 7.0.2
Copyright (C) 2005-2022 Oracle and/or its affiliates

VBoxManage: error: Invalid command 'uninstall'

Usage - Oracle VM VirtualBox command-line interface:
....

違うらしい

$ sudo VBoxManage extpack uninstall "Oracle VM VirtualBox Extension Pack"
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Successfully uninstalled "Oracle VM VirtualBox Extension Pack".

行けた。Pack no. 0: の行が名前だった。この名前いつも一緒なんじゃないの?意味あんの?って思った。sudo入れてるのはリモート環境でやってるから。直でやってるならおそらく不要。

新しいバージョンをインストールする。ファイル名を指定すればよさそう

$ sudo VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-7.0.2.vbox-extpack

ライセンスが表示されるのでyで応答すると

0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Successfully installed "Oracle VM VirtualBox Extension Pack".

インストールされた。

[docker]止まってるコンテナにシェルでアクセスする

起動してもすぐ止まってしまうコンテナがあって、大したログも出てなかったのでシェルで入って調査しようと思ったらうまくいかなかった。

調べると`docker commit -t` でimageを作るというのが出てくるのだけど、実際やってみるとコマンドのオプションが間違っていると言われてしまう。

$ docker commit -t exited 8300cc1f5905
unknown shorthand flag: 't' in -t
See 'docker commit --help'.

なくなったオプションの -t は何だか分からないけどなくてもよさそう。

$ docker commit 8300cc1f5905
sha256:79a026a4101911e1e988fee4d15ed3bc7e115c3df11a00a402659886b81dfbb6

このハッシュを使って起動すればいい

$ docker run --rm -it 79a026a4101911e1e988fee4d15ed3bc7e115c3df11a00
a402659886b81dfbb6

これでシェルアクセスすることができた。

run-asできないけどSharedPreferencesを見たい

あくまで自分で開発してるときの話です。他人が作ったアプリのは見られません。

SharedPreferencesが見られなくて困った。プログラム上からは取得/更新できるけど、実際にファイルにどう書かれているか知りたかった。

adb shellから、run-asコマンドを使っても

run-as: package has corrupt installation

と出て、表示できない。

Android StuidioでView -> Tool Windows -> Device File Exploreを使っても同じメッセージが表示されて表示できない。

原因を調べてもよく分からない。

インストールし直してみたりしたけどメッセージは変わらない。

しょうがないのでコードで書き出すことに。

MainなActivityに以下の関数を作る

    protected fun showFiles(filter: FileFilter? = null, print: Boolean = false, path: File? = null ) {
        val targetPath = path ?: File("/data/data/" + packageName)

        if (targetPath.isDirectory) {
            if (filter == null || filter.accept(targetPath)) {
                Log.d("showFiles", "dir: ${targetPath.absolutePath}/");
            }
            targetPath.listFiles().forEach { file -> showFiles(filter, print, file) }
        } else {
            if (filter == null || filter.accept(targetPath)) {
                Log.d("showFiles", "file: ${targetPath.absolutePath}");
                if (print) {
                    Log.d("showFiles", "content: ${targetPath.readText()}")
                }
            }
        }
    }

そして、onCreateで引数なしで呼んでみる

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        showFiles();
...

logcatにファイル名が出てくる。

自分が使ってるファイル名が分かったら、こんどはonCreateで引数つけて呼んでみる。

今回は”config”という名前をつけてたのが分かったので、

showFiles(FileFilter {pathname -> pathname.endsWith("config.xml") }, true);

という呼び出しに変更して実行すると、 config.xmlファイルがlogcatに表示される。