OpenSSH経由のリモートログインではGUIアプリケーションは起動できない

前回までで、PowerShell 7.2の主な新機能については一通り紹介したので、連載の流れに戻ろう。

リモートワークで重要な役割を果たしているものの一つがOpenSSHだ。LinuxなどのUNIX系OSでは、OpenSSHを経由してサーバにログインして作業をすることが多い。Windowsでも、OpenSSHサーバ/クライアントは標準搭載されており、OpenSSH経由でログインして作業することができるようになっている。

OpenSSHのセットアップさえしてしまえば、WindowsでもLinuxサーバと同様にリモートログインで作業を行える。ただし、Windowsの場合はOpenSSH経由でリモートログインして実行できるプログラムはコンソールベースのソフトウエアに限られている。

例えば、次のスクリーンショットはMacからWindows 11へOpenSSH経由でリモートログインしたところだ。Windows 11にOpenSSHサーバをセットアップしてあるので、Macからリモートログインできている。

  • MacからWindows 11へOpenSSH経由でリモートログイン

    MacからWindows 11へOpenSSH経由でリモートログイン

リモートログインしたWindows 11でコマンドが実行できることも確認できる。

  • PowerShell 7が起動し、コマンドが実行できている

    PowerShell 7が起動し、コマンドが実行できている

しかし、「メモ帳」のようなGUIアプリケーションを起動しようとしても、何も実行されない。

  • OpenSSHでリモートログインした状態ではメモ帳は起動できない

    OpenSSHでリモートログインした状態ではメモ帳は起動できない

さらに、上記のようにメモ帳の起動を試みると、これまでPowerShell 7から起動できていても起動できなくなったりする。

  • なぜかWindows 11からも起動できなくなったメモ帳

    なぜかWindows 11からも起動できなくなったメモ帳

このように、OpenSSH経由でリモートログインした状態ではGUIアプリケーションは起動できない上、おかしな状態になってしまう。

物理的にサインインした場合や、リモートデスクトップ機能でサインインした場合と、OpenSSH経由でリモートログインした状態では、ユーザーが実行できる“範囲”が異なる。GUIアプリケーションを実行するのであれば、物理的にサインインするか、リモートデスクトップ機能経由でサインインする必要がある。これはもう、そのように作られているからであり、オプションを指定すれば起動するようになるとか、そういう話ではない。

でも、その機能が欲しい

しかし、だ。OpenSSH経由でリモートログインした状態でGUIアプリケーションを起動したいこともある。

例えば、主にWSL2で動作するUbuntuで作業しているとか、Hyper-Vなどの仮想環境上で動作するUNIX系OSでの作業を行っている、または、Hyper-V上の仮想環境で動作するWindowsで作業していてもよい。そういった環境から、ホストのWindowsでGUIアプリケーションを起動したいことがある。

対象はメールアプリケーションやVisual Studio/Visual Studio Code、Webブラウザとさまざまなものが考えられるが、とにかく仮想環境からホストのWindowsでシームレスに起動してほしいのだ。もう少し具体的に言うと、シェルスクリプトやインタラクティブシェルから一発でGUIアプリケーションを起動したい。つまり、やっぱりOpenSSH経由でGUIアプリケーションを起動したいのである。

では、どうするのか

とはいえ、OpenSSH自体がその機能を提供していないのだから、ほかの方法で実現する必要がある。

シンプルに考えると、外部から指定されたGUIアプリケーションを起動するサービスを開発すればよい。UNIX系のOS的に言えば、サーバないしはデーモンを開発することになる。そのサービス自体は、Windowsのホスト環境でGUIアプリケーションを実行できる状態で起動しておく。サービスは常にクライアントからの要求を監視し、要求が来たらそれに応じてGUIアプリケーションを実行するのである。

実のところ、こういったサービスはPowerShellで結構簡単に開発できる。while文でぐるぐる回りながらアクセスを待って、アクセスがあったらそれを実行すればよい。Windowsにはサービスを自動起動するためのタスクスケジューラも用意されているので、UNIX系OSのサーバのように動かすことができるのだ。

PowerShellスクリプトでサービスを開発するというのは、PowerShellを業務で使う上で興味深いサンプルになるはずだ。しばらくは、この方法を紹介していこうと思う。

最初に、最後の成果物の話をしておこう。すでに前述のサービスが起動している状態で、次のように特定のファイルに文字列を書き込む。

  • 特定のファイルに文字列を書き込む

    特定のファイルに文字列を書き込む

PowreShellで開発されたサービスはこのファイルを監視しており、書き込みがあるとその中身を読み込んで実行する。上記のスクリーンショットでは「notepad」と書き込まれているので、サービスによってnotepad(メモ帳)が実行される。

  • ファイルに書き込まれた文字列が実行され、この場合はメモ帳が起動してくる

    ファイルに書き込まれた文字列が実行され、この場合はメモ帳が起動してくる

サービス側では、次のようにログを出力している。

  • サービスがログを出力しているところ

    サービスがログを出力しているところ

このようにサービスを開発しておけば、後はsshでリモートログインしてファイルへ起動したいコマンドを書き込むだけでよい。この作業はインタラクティブに行う必要はなく、sshコマンドライン一発で行うことができる。ここまでできれば、やりたいことは実現できたと言えるだろう。

必要な機能は自分で作る

既存のソフトウエアがオプションとして機能を提供してくれているのであれば、それを使ったり、カスタマイズしたりすればよい。もし、用意されていない場合は、今回説明したように自分で作ればよい。

この作業は場合によってはとても面倒な(低いレベルから開発を行う必要があるという意味で)ことになる可能性があるが、場合によってはちょっとした発想の転換で非常に簡単に実現できることもある。今回のように、「OpenSSH経由でリモートログインしている場合でもGUIアプリケーションを起動したい」というのは、どちらかと言うと後者だ。

PowerShellでシンプルなサービスを開発する方法として、参考にしていただきたい。