コマンドによっては、処理の途中で、ユーザーに対して続行の可否を尋ねてくるものがある。大抵「y/n?」というメッセージが表示され、「y」または「n」の入力を求めてくるスタイルだ。求められる文字は「YES」だったり「yes」だったりすることもあるが、問題は人間がインタラクティブに入力しなければいけないという点にある。

サーバ管理に慣れてくると、時間のかかる処理はコマンドを実行してから席を立ち、コーヒーを飲んだりして一服している間に終わるのを待つ……といった行動パターンになるのだが、これが途中で「y/n?」の入力を求めてくる処理だと、そこで一時停止してしまう。

# pkg upgrade
...略...
Checking for upgrades (283 candidates): 100%
Processing candidates (283 candidates): 100%
The following 123 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        mesa-libs: 17.1.4
        libunwind: 20170113_1
        libidn2: 2.0.2
        python36: 3.6.1_4
        gcc5: 5.4.0_2
        rhash: 1.3.4

Installed packages to be UPGRADED:
        webp: 0.5.2_1 -> 0.6.0_3
        vim: 8.0.0507 -> 8.0.0670
        tpm-emulator: 0.7.4_1 -> 0.7.4_2
        texinfo: 6.1.20160425,1 -> 6.3_2,1
        sudo: 1.8.20p1 -> 1.8.20p2_2
        sqlite3: 3.17.0 -> 3.19.3_1
...略...
        cmake-modules: 3.7.2 -> 3.8.2
        cmake: 3.7.2 -> 3.8.2
        cairo: 1.14.8,2 -> 1.14.8_1,2
        automake: 1.15_1 -> 1.15.1
        atk: 2.18.0 -> 2.24.0
        GraphicsMagick: 1.3.25_2,1 -> 1.3.25_3,1

Installed packages to be REINSTALLED:
        unibilium-1.2.0
        tcl86-8.6.6_2
        python3-3_3 (direct dependency changed: python36)
        png-1.6.29
        pixman-0.34.0
...略...
        libSM-1.2.2_3,1
        libICE-1.0.9_1,1
        lcms2-2.8
        gnutls-3.5.13 (direct dependency changed: libidn2)
        giflib-5.1.4
        fontconfig-2.12.1,1
        fish-2.5.0 (direct dependency changed: python36)
        avahi-app-0.6.31_5

Number of packages to be installed: 6
Number of packages to be upgraded: 75
Number of packages to be reinstalled: 42

The process will require 120 MiB more space.
481 MiB to be downloaded.

Proceed with this action? [y/N]: ← ここで処理が入力待ち状態になる

席に戻って処理が終わっていないコマンドを見たときの残念感は言い知れない。場合によっては残業が必要になってしまうかもしれない。そんな事態の回避に使えるのが、yesコマンドだ。

インタラクティブな入力を求めてくるコマンドを実行する際、あらかじめパイプでyesコマンドをつなげておく。これにより、入力を求められると、次のように自動的に「y」が入力されるようになる。

# yes | pkg upgrade  ← yesコマンドからつなげる
...略...
Checking for upgrades (283 candidates): 100%
Processing candidates (283 candidates): 100%
The following 123 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        mesa-libs: 17.1.4
        libunwind: 20170113_1
        libidn2: 2.0.2
        python36: 3.6.1_4
        gcc5: 5.4.0_2
        rhash: 1.3.4

Installed packages to be UPGRADED:
        webp: 0.5.2_1 -> 0.6.0_3
        vim: 8.0.0507 -> 8.0.0670
        tpm-emulator: 0.7.4_1 -> 0.7.4_2
...略...
        automake: 1.15_1 -> 1.15.1
        atk: 2.18.0 -> 2.24.0
        GraphicsMagick: 1.3.25_2,1 -> 1.3.25_3,1

Installed packages to be REINSTALLED:
        unibilium-1.2.0
        tcl86-8.6.6_2
        python3-3_3 (direct dependency changed: python36)
...略...
        fontconfig-2.12.1,1
        fish-2.5.0 (direct dependency changed: python36)
        avahi-app-0.6.31_5

Number of packages to be installed: 6
Number of packages to be upgraded: 75
Number of packages to be reinstalled: 42

The process will require 120 MiB more space.
481 MiB to be downloaded.

[1/123] Fetching webp-0.6.0_3.txz: 100%  389 KiB 398.7kB/s    00:01    %
[2/123] Fetching vim-8.0.0670.txz: 100%    6 MiB 452.1kB/s    00:15
[3/123] Fetching unibilium-1.2.0.txz: 100%  114 KiB 117.2kB/s    00:01
...略...
[121/123] Fetching python36-3.6.1_4.txz: 100%   15 MiB 283.7kB/s    00:54
[122/123] Fetching gcc5-5.4.0_2.txz: 100%   81 MiB 317.1kB/s    04:27
[123/123] Fetching rhash-1.3.4.txz: 100%  133 KiB 136.4kB/s    00:01
Checking integrity... done (5 conflicting)
Checking integrity... done (0 conflicting)
Conflicts with the existing packages have been found.
One more solver iteration is needed to resolve them.
The following 128 package(s) will be affected (of 0 checked):

Installed packages to be REMOVED:
        libglapi-13.0.6
        gbm-13.0.6
        libGL-13.0.6
        libEGL-13.0.6

New packages to be INSTALLED:
        libunwind: 20170113_1
        mesa-libs: 17.1.4
        libidn2: 2.0.2
        python36: 3.6.1_4
        gcc5: 5.4.0_2
        rhash: 1.3.4

Installed packages to be UPGRADED:
        pciids: 20170316 -> 20170622
        libpciaccess: 0.13.4 -> 0.13.5
        readline: 6.3.8 -> 7.0.3
...略...
        cmake: 3.7.2 -> 3.8.2
        automake: 1.15_1 -> 1.15.1
        GraphicsMagick: 1.3.25_2,1 -> 1.3.25_3,1

Installed packages to be REINSTALLED:
        libxml2-2.9.4
        libXdmcp-1.1.2
        libXau-1.0.8_3
...略...
        libarchive-3.3.1,1
        lcms2-2.8
        fish-2.5.0 (direct dependency changed: python36)

Number of packages to be removed: 4
Number of packages to be installed: 6
Number of packages to be upgraded: 74
Number of packages to be reinstalled: 42

The process will require 533 MiB more space.

Proceed with this action? [y/N]: ← ここに自動的に「y」が入力される
[1/128] Reinstalling libxml2-2.9.4...
[1/128] Extracting libxml2-2.9.4: 100%
[2/128] Reinstalling libXdmcp-1.1.2...
[2/128] Extracting libXdmcp-1.1.2: 100%
...略...
[126/128] Upgrading automake from 1.15_1 to 1.15.1...
[126/128] Extracting automake-1.15.1: 100%
[127/128] Upgrading GraphicsMagick from 1.3.25_2,1 to 1.3.25_3,1...
[127/128] Extracting GraphicsMagick-1.3.25_3,1: 100%

%

コマンドによってはオプションを指定することで自動的に「y」を入力するように設定できるものもあるが、そんなオプションの無いコマンドもある。そこで威力を発揮するのが、このyesコマンドというわけだ。ファイルを削除する処理なども、yesコマンドからパイプでつないで実行すると、ユーザーによる確認入力を省略できる。

「一体、このyesコマンドは何をしているのか」と思うかもしれない。実は、次のように「y」を無限ループで出力しているだけだ。

% yes
y
y
y
y
y
y
y
y
y
y

また、yesコマンドの引数に文字列を指定すると、その指定した文字列を無限ループで出力してくれる。

% yes agree
agree
agree
agree
agree
agree
agree
agree
agree
agree
agree

yesコマンドは便利なので、どんどん使っていただきたい。なお、入力値が「y」「n」「y」のように同じ文字列ではない場合には「printf ‘y\nn\ny\n’」のようにコマンドを実行し、これをパイプで接続して次のコマンドへ流し込めば、似たような自動化処理を実現できる。

将来を通じて、楽をするために使えそうなコマンドを積極的に覚えて活用していく。これが、作業の手間を減らす近道だ。この機会にぜひ、yesコマンドも覚えてもらえればと思う。