バックアップや大容量ファイルの変換など、処理に長時間かかるタスクを実行している間にPCがスリープしてしまい、処理が中断して困った経験はないだろうか。今回は、明示的にPCのスリープを禁止するコマンドをGo言語で作成する方法を紹介する。WindowsとmacOSで異なる処理を行う方法も解説する。
macOSには標準のスリープ禁止コマンドが存在
macOSには、最初から「caffeinate」というコマンドが用意されている。このコマンドを実行している間は、OSがスリープにならない。名前は日本語で「カフェインを与える」という意味で、Macにコーヒーを飲ませて眠らせないようにするという洒落が効いている。
一方、Windowsにはこのコマンドがデフォルトで用意されていない。そこで、WindowsとmacOSの両方で使えるスリープ禁止コマンドを自作する。
Go言語で両OS対応ツールを簡単に作成
WindowsとmacOSの両方の実行ファイルを作成できるツールを効率的に作るには、Go言語が便利だ。両方のプラットフォームで使える実行ファイルを一気に生成できる。
Windowsには、もともとSetThreadExecutionStateというWindows APIが用意されており、Go言語からこのAPIを呼び出せば、スリープ禁止コマンドを作成できる。Go言語ではシステムに用意されている機能を手軽に呼び出せるのが利点だ。
macOSには「caffeinate」コマンドがあるので、そちらを実行するだけで事足りる。
WindowsとmacOSで処理を切り替える方法
今回のプログラムでは、WindowsとmacOSで利用する機能を切り替える必要がある。WindowsではOSのAPIを呼び出し、macOSではコマンドを実行する。そこで、次のようなファイル構成にする。
- main.go --- メインプログラム
- sleep_windows.go --- Windows用の実装ファイル
- sleep_darwin.go --- macOS用の実装ファイル
メインプログラム「main.go」には共通処理を記述し、preventSleep()関数の実装だけをOSごとのファイルに分ける。ファイル名の末尾を「_windows.go」や「_darwin.go」とすることで、Goのビルドツールが対象OSに応じて必要なファイルだけを自動的にコンパイルする。
両方のファイルで同じ関数名 preventSleep() を定義しておけば、main.goからはOSを気にせず呼び出せる。呼び出し側のコードは1つで済み、中身の実装だけがOSごとに切り替わる仕組みだ。
プログラムの実装と実行方法
今回のプログラム全体はGitHubにアップロードされており、「Source Code(zip)」からソースコードをダウンロードできる。メインプログラムでは、preventSleep()関数を呼び出し、引数なしの場合はCtrl+Cで終了するまでスリープ禁止状態を維持する。
Windows版のpreventSleep()関数は、runtime.LockOSThread()でgoroutineを現在のOSスレッドに固定し、kernel32.dllのSetThreadExecutionStateを呼び出す。引数にesContinuousとesSystemRequiredを指定することでスリープを禁止する。設定はスレッド単位なので、確実にスリープを禁止するためにスレッドを固定している。
実行ファイルは、以下のコマンドで生成できる。
# Windowsの場合go build -o nosleep.exe# macOSの場合go build -o nosleepターミナル上で「nosleep」を実行している間はスリープ禁止状態になり、解除するにはCtrl+Cを押す。なお、スリープ禁止はアイドル状態からのスリープを防ぐもので、ユーザーが明示的にスリープボタンを押したり、ノートPCの蓋を閉じたりした場合はスリープになる点に注意が必要だ。
Go言語でOSごとにファイルを分けて実装することで、WindowsとmacOSの両方で動くスリープ管理ツールを簡単に作成できる。スリープ管理はOSと結びついた処理だが、この方法なら同じプログラムで両OSに対応できる。



