screenは、ひとつの物理的な端末を複数のプロセス (特に対話シェル) で共有化できるようにする、フルスクリーンウィンドウ管理ソフトウェアである。 - https://kazmax.zpp.jp/cmd/s/screen.1.html
目次
前書き
Linuxにはscreenという便利な機能がある。これを使う利点としては、「実行に長時間かかるプロセスを別セッションで実行させて、シェルを使えるようにしておく」といったものがある。
例を挙げるならば「Minecraftサーバー」。noguiモードで起動すると、ターミナルをサーバーコンソールとして実行する。(nogui無しでもguiウィンドウが開くだけでターミナルからも受け付けてたかもしれないが・・・)
つまり、サーバーを動作させている間はターミナルのコマンドは実行できない。別のターミナルを開けば実行できるが、CUIのOSである場合はそうはいかない。
という訳で、別セッションを作成しそこでMinecraftサーバーを実行させることでバックグラウンドで起動する事が出来る、という訳だ。
screenでサーバーを起動するって?
じゃあどうやって別セッションでサーバーを起動するのかというと、別著者のサイトを引用する形になるが
screen java -jar サーバーのjarファイル nogui
というように、screenコマンドの引数で別のコマンド(今回はjava)を実行することで別セッションで実行する事が出来る。
本題に入る。このサイトからの引用で、
screen -UAmdS minecraft java -server (中略、ここはJVM引数) -jar ${JARFILE} nogui
(今回の記事とは関係ないが、serverオプションを付けたほうが(クライアントコンパイルからサーバーコンパイルに変更するらしい。詳しい仕組みはそのうち気が向いたら調べる。)処理速度が速くなるらしい。書き直しとこ。)
ん?
「-UAmdS」って、何?
これが本題だ。なのでscreenでサーバーを起動したいだけなら他の、というか先ほど引用したのやり方を行っていただきたい。
screenコマンドのオプション
自分は-AdmSUで使っていたが、このオプションはまとめる事が出来るっていうのが大前提。(知らない人いたから)
という訳で、これは -A -d -m -S -U というオプションとなる。
そして、もう一つ。実は「screen java -jar jarファイル nogui」でもちゃんと別セッションとして実行できるが、紹介記事ではよくこのオプションが付けられている。
オプションが解説されたページ
-Aはウィンドウサイズの調整、-Sはセッション名の設定(screen -r セッション名でアタッチする事が出来る。セッション名を指定しない場合はプロセスIDを指定してアタッチできる。)、-UはUTF-8モードでの起動を意味する。(日本語使うから必要なのか、これはよく分からない)
で気になったのが、「-d -m(ひとセットなので-d -mだろうが-m -dだろうが-md,-dmでもいい)」というオプションだ。
特に何も考えずに使っていたが、
-d -mscreenを QdetachedU モードで起動する。新たなセッションが生成されるが、 そのセッションへアタッチしない。 これはシステムのスタートアップスクリプトで便利である。
これはなんだ。
QdetachedUモード?
とかずっと考えていたのだが、調べているとただのデタッチモードで起動するだけらしい。
でも、必要なのか?
デタッチモード
先ほどちょっと出てきたワードで「アタッチ」もあったが、これはセッションへ接続することを意味する。デタッチはセッションから切断するという事だ。ただし、セッションはどこにもアタッチしていなくてもバックグラウンドで動作し続ける。
screenで起動してCtrl A→Dを入力することでデタッチできるなどという機能もある。
screenでセッションを作成すると通常は実行したターミナル上でそのままアタッチしている状態となる。しかし、このオプション(-dm)を付けることでアタッチしない。セッションが作られるだけとなる。
まあ、あれば便利だな程度
だと
思った。
問題が起き、この疑問が発生
先日から相談に乗っているこのブログの読者とやり取りをしていて、「-dmオプションないまま起動してもええやろ~って思って起動したら、[screen is terminaring]の表示が出てサーバーが起動しなかった・・・」と言われた。厳密には起動しない趣旨だけ伝えられたが、消した-dmオプションを付けなおしたら起動できたらしいので原因はすぐ解明された。
これについてをまとめたいっていうのがこの記事なのだが、そもそも「screen java -jar jarファイル nogui」で問題なく実行できるという話をしたし、このオプションがない状態でターミナルで実行してもちゃんと実行する事が出来る。
じゃあ何故実行できなかったのか、
それは「crontab」で定期的に実行するシェルスクリプトであったから、だ。
考察 何故screenがcronで実行できないのか
一応、私が考えている考察としては「crontabプロセスがスクリプトを実行しているから、screenがcrontabプロセスのフォアグラウンドで実行しようとして失敗したのではないか?」と考えた。(Linux初学者なので何も知らないのは許してほしい)
という訳でcronについて調べるところから始めてみる。
調べてみて、cronが「クーロン」ではなく「クローン」と読むことすら今初めて知った、そんなレベルだ。
crontabとは
「Regular background program processingdaemon」とある。普通のバックグラウンド常駐プログラムだそうだ。
まあ簡単に言ってしまえば、設定したルール通りに定期的に指定された時刻(もしくは起動時(@reboot)に)にコマンドを実行してくれるプログラムだ。バックアップ、再起動、とか色々な用途に使える便利な機能。
do not have a terminal
そしてこんなstackoverflowを見つけた。
In cron, you do not have a terminal (see for example Linux: Difference between /dev/console , /dev/tty and /dev/tty0). screen wants to run in a terminal. Getting it to run in that situation requires special handling.
「ターミナルがない」だから実行できなかったのか( ^ω^)・・・スッキリした。
あとリンクがちょっと乗っかってるのをちょっと調べてみると
/dev/tty0 Current virtual console/dev/tty Current TTY device
/dev/console System console
TTYはもともとコマンドラインでの操作やコマンドの出力結果を対話的に行うためのインターフェースのこと。
らしい。
つまりターミナルのアレか。調べていると、cronでsudo(スーパー権限実行を行うコマンドで、パスワードの入力を対話式に求める)を実行すると、「sudo: 端末 (tty) が存在せず、パスワードを尋ねる (askpass) プログラムが指定されていません」とエラーが出るそうだ。
本題とは外れるが、この場合の対策で紹介されているのが「パスワード無しでsudoを実行する」という方法があるらしいが、普通にセキュリティ的に危ないと思うのでこの方が紹介している通り、rootのcrontabに実行したほうがいいと書いてあるのでこれを見た人はそうしよう。
(自分への戒めも兼ねてる)
話を戻すと、cronにはこのtty、つまり対話的に行うインターフェースがない(なんならリダイレクトでどっかファイルに出力しないと実行したログすら出力しない)のでttyを必要とする処理は実行できないのだろう。
・・・ん?screen関係ある?
結論 screenがcronで実行できない理由
結論を言うと、screenは常にキーボード入力を受け付けているため、対話式でのプログラムとなっているのではないか。
なのでttyが無かったらsudo実行時と同じようなエラーを吐く。
・・・のではないか。tty無しでも別に動きそうじゃね?とも思うので、もし違う原因があるのだと判明したら後々追記する。
最後に、少し調べたらこういう投稿が見つかった。やはり、ttyが存在しないとエラーを吐いてscreenは実行できないようだ。
対話的なやり取りが必要なセッション、プロセスはttyがないcronとかだと「そもそも」実行できないのか。初めて知った。
対話式の仕組みってよく分かっていなかったので、今回知れてよかった。
0
この記事へのコメント