Ubuntu:ルーチン化した日々のコマンドを実行するシェルスクリプト

新規ターミナルから任意のコマンドを複数タブで連続実行するシェルスクリプト

気がつけば、PCを起動・再起動するたびに複数のサーバを起動したりして、何か作業する際に必ずいつも同じコマンドを新規のターミナルとか新規タブとか開いて叩いています。もっと便利なやりかたはないのでしょうか?

ということで、シェルスクリプトからまず新規ターミナルを開き、そのターミナル上で任意のコマンドを複数タブで自動的に連続実行させる方法を考えてみました。

シェルスクリプトの基本的なこと

HOME/bin/シェルスクリプトを書いておけば、任意のコマンドを実行できます。ちなみに「端末」とか「ターミナル」とか書きますが、ここでの意味は同じです。

[~/bin/test.sh]

#!/bin/bash
実行したいコマンド

必ず実行権限を与えておきます。

$ chmod 755 ~/bin/test.sh
$ ./test.sh

例えば

#!/bin/bash

echo "Hello Bash!"

で実行した端末に「Hello Bash!」と出力されます。

WEBサーバの起動のような、起動後にログとして出力されるその都度の処理結果を見たい場合、この書き方だと実行した端末にログが出力されCtrl-cで終わらせないかぎりその端末で他の事ができません。Linuxを始めた頃はよくわかっていなかったので、処理を終わらせるか、別のターミナルを開くなどしていました。

新規ターミナルでシェルスクリプトを実行する。

そこでまず、次のように書いて新規ターミナルで実行させます。先頭の#!/bin/bashはときどき省略しますが、必ず書かれているものと思ってください。

[~/bin/test.sh]

gnome-terminal -- 実行したいコマンド

ただしechoのような1回かぎりの結果を見たいコマンドでこれをやっても意味ありませんし、処理結果を出力して終わるようなコマンドは処理終了後にターミナルウィンドウが閉じてしまいます。ログを出力するコマンド、例えばtopなどをこのスクリプトに続けて書いてもtopの処理は実行した端末側に出力されます。

gnome-terminal -- echo "Hello Bash!"; top

これだとgnome-terminal --topにかかっていないので、topの処理が別端末に表示されないのは当たり前。コマンドの書き方の意味がわかっていないうちはこういうピンボケをやってしまいがちですw

スクリプト実行後にターミナルウィンドウを開いておく

スクリプトを実行すると新規ターミナルが開かれて、そこにログが出力されるようにしたいですね。その場合はこう書きます。

gnome-terminal -- bash -c "echo 'Hello Bash!'; top"

新規ターミナルに「Hello Bash!」と出力されたあとtopのログが開始されてます。

test.sh

bashcオプションは「コマンドを後に続く文字列から読み込む」というもののようです。

kazmax.zpp.jp

ターミナルのタブでスクリプトを実行

次のように書くことで、新規ターミナルで端末プロファイル名を指定し~/webserver/server_index.jsnodeコマンドで実行し、ExpressのローカルWebサーバを起動させます。

# 1.start express webserver port:8002
gnome-terminal --window --profile=profile1 -- bash -c "cd ~/webserver/; node server_index.js"

端末プロファイル名を指定するのは、文字の大きさや端末画面サイズなどを好みに設定した形で開きたいからです。

次のようにオプション--window--tabと書くと、新規ターミナルではなくスクリプトを実行した端末に新規タブを開いて同じようにWEBサーバが起動します。

gnome-terminal --tab --profile=profile1 -- bash -c "cd ~/webserver/; node server_index.js"

日常使うコマンドを複数タブで連続実行させる例

日常的にしていることとして、メインPCと外付けHDのそれぞれでWEBサーバを別ポートで立ち上げてブラウザで閲覧できるようにしています。またHugoでサイトを作る作業が多いのでとりあえずhugo serverコマンドを起動しています。この3つのコマンドをいちいち新規タブを選んで実行するのは面倒ですね。

そこで次のようなスクリプトを書いてみました。

まず3つのタブでそれぞれのコマンドを実行するスクリプトを「daily_routines.sh」として書きます。

[~/bin/daily_routines.sh]

#!/bin/bash

# 1. start hugo port:1314(Hugoサーバの起動)
gnome-terminal --tab -t "Hugo Server" --profile=profile1 -- bash -c "cd ~/MyCode/siteHugo/; hugo server -p 1314 --ignoreCache; bash"

sleep 1

# 2. start express webserver port:8002(PC側Expressサーバの起動)
gnome-terminal --tab -t "Express on PC" --profile=profile1 -- bash -c "cd ~/webserver/; node server_index.js"

sleep 1

# 3. start express webserver port:8003(外付けHD内を見るためのExpressサーバの起動)
gnome-terminal --tab -t "Express on external HD" --profile=profile1 -- bash -c "cd /media/user/webserver/; node server_index.js"

連続実行するときに全く間隔を開けずにやるとうまくいかない場合があるようです。なのでsleepを挟んでいます。

またHugoサーバの起動コマンドにだけは末尾にbashとついています。Hugoサーバは開発中に停止や再起動をよくするので、サーバを停止させても端末を閉じないようにさせたい。bashとつけることでCtrl-cでサーバを停止させてもターミナルは残ります。

このスクリプトを直接実行すると、こんな感じで実行した端末にタブが3つ開いて起動します。

できれば別の新規端末で最初のスクリプトを走らせて、その端末にあとの2つを新規タブで実行させたい。スクリプトを実行する最初の端末は残しておいて、別の用途に使いたいわけです。WEBサーバなどは、作業の横で別個に走っていてほしいので。

最初は、1番目のコマンドにwindowオプションを付けて走らせると、あとの2つのタブがそこに開くと思ったのですが違いました。最初のは新規で。あとの2つは実行元の端末に新規タブで開かれます。そこでオプションは3つともtabのままで、このスクリプトを起動するだけのスクリプトを作ります。

[~/bin/start_droutines.sh]

#!/bin/bash

# start daily routines
gnome-terminal --window -- bash daily_routines.sh

これでうまくいきました。

start_droutines.sh

gnome-terminalのオプション

調べついでに、コマンドラインから--helpで確認できるgnome-terminalのオプションを記しておきます。

$ gnome-terminal --help
用法:
  gnome-terminal [OPTION…] [-- COMMAND …]

ヘルプのオプション:
  -h, --help                      ヘルプのオプションを表示する
  --help-all                      ヘルプのオプションをすべて表示する
  --help-gtk                      GTK+ のオプションを表示する
  --help-terminal                 端末のオプションを表示する
  --help-window-options           ウィンドウ毎のオプションを表示する
  --help-terminal-options         端末毎のオプションを表示する

アプリケーションのオプション:
  --load-config=FILE              端末の設定ファイルを読み込む
  --preferences                   設定ウィンドウを表示する
  -p, --print-environment         Print environment variables to interact with the terminal
  -v, --verbose                   Increase diagnostic verbosity
  -q, --quiet                     抑えた出力
  --display=DISPLAY               使用するXのディスプレイを指定する

ターミナル共通のオプション

$ gnome-terminal --help-terminal
用法:
  gnome-terminal [OPTION…] [-- COMMAND …]

新しいウィンドウやタブを開くオプション (これらのオプションを1つ以上指定できる):
  --window                        デフォルトのプロファイルでタブ付きのウィンドウを開く
  --tab                           デフォルトのプロファイルで最後に開いたウィンドウの中にタブを開く

ウィンドウ毎のオプション

$ gnome-terminal --help-window-options
用法:
  gnome-terminal [OPTION…] [-- COMMAND …]

ウィンドウのオプション (引数で最初に現れる --window あるいは --tab より前の位置で指定すると、すべてのタブやウィンドウに適用される):
  --show-menubar                  メニューバーを表示する
  --hide-menubar                  メニューバーを隠す
  --maximize                      ウィンドウを最大化する
  --full-screen                   ウィンドウをフルスクリーンにする
  --geometry=GEOMETRY             ウィンドウサイズを設定する。 例: 80x24、80x24+200+200 (列x行+X+Y)
  --role=ROLE                     端末の役割を指定する
  --active                        最後に指定したタブをそのウィンドウの中で有効にする

ターミナルごとのオプション

$ gnome-terminal --help-terminal-options
用法:
  gnome-terminal [OPTION…] [-- COMMAND …]

端末のオプション (引数で最初に現れる --window あるいは --tab より前の位置で指定すると、すべてのタブやウィンドウに適用される):
  -e, --command                   端末内でこのオプションに対する引数を実行する()
  --profile=PROFILE-NAME          指定したプロファイルを使用する
  -t, --title=TITLE               端末の初期タイトルを設定する
  --working-directory=DIRNAME     作業用ディレクトリを指定する
  --wait                          子が終了するまで待つ
  --fd=FD                         ファイルデスクリプターを転送
  --zoom=ZOOM                     端末の拡大率を指定する (1.0 = 標準サイズ)

(※) -eオプションは、現在非推奨のようです。

参考になった記事

https://linuxfan.info/gnome-terminal-with-command

qiita.com