Apache2でcgiを使いアクセスされたときに自動的にサーバーでコマンドを実行する方法 (2021/08/06)

今回はBashのシェルスクリプトを使います。少し改造すれば他のシェルスクリプトも使えます。

初期設定

まず、Apache2をインストールしていなければインストールします。

if apache2 -h > /dev/null 2>&1
    then
    sudo apt install apache2
    else
    echo "already installed."
fi

そしたら、cgi-binフォルダを作成し、Apache2でmod_cgidを有効化します。
sudo mkdir /var/www/cgi-bin -p
sudo chown www-data /var/www/cgi-bin -R
sudo chmod a+r /var/www/cgi-bin -R
sudo chmod g+x /var/www/cgi-bin -R
sudo chmod u+w /var/www/cgi-bin -R
sudo a2enmod cgid
cat << "EOF" | sudo tee /etc/apache2/apache2.conf -a
LoadModule cgid_module modules/mod_cgid.so
AddHandler cgi-script .cgi
Alias /cgi-bin/ "/var/www/cgi-bin/"
<Directory /var/www/cgi>
        Options FollowSymLinks ExecCGI
        AllowOverride None
        Require all granted
</Directory>
EOF
そして、
sudo nano /etc/apache2/apache2.conf
で、apache2の設定を編集します。 実は言うと、okaitsの能力不足でシェルスクリプトにできなかったからです。(笑)
<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>
を探して、その中の
Options Indexes FollowSymLinks
Options FollowSymLinks ExecCGI
にして、
nanoを保存して終了します。
なお、nanoの操作方法は下に書いてあります。
それがおわったら、
sudo systemctl reload apache2
sudo systemctl restart apache2
でapache2を再起動させてください。

シェルスクリプトを入れる方法

まず、/var/www/cgi-bin/の中に、ファイル名.cgiという名前のファイルを作ります。
または、すでにあるシェルスクリプトを/var/www/cgi-bin/にコピーし、拡張子をcgiにしてください。
作った/コピーしたファイルの先頭に、

#!/bin/bash
echo "Content-type: text/plain"
echo
と入れてください。
なお、
echo "Content-type: text/plain"
echo "Content-type: text/html"
に置き換えるとただのtxtファイルからhtmlファイルになります。
cgiでは、コマンドの実行結果がソースコードとして認識されます。
つまり、
echo '<p class="container">ABC</p>'
をcgiファイルに書いてアクセスすると、
<p class="container">ABC</p>
と解釈され、ABCと表示されます。

#!/bin/bash
echo "Content-type: text/plain"
echo
echo "Suspended."
sudo /usr/bin/systemctl suspend
これを公開したら誰もが自由にサーバーをサスペンドさせることができるようになります。()
BASIC認証など、絶対に他人に突破されない方法をつかってアクセスを制限してください。
なお、これはcurlでも反応するので、このsuspend.cgiを使って、こんなこともできます。
これはGithubにPushしてからサスペンドするというプログラムです。
Jekyllでブログやってる人は、書き終えてからCommit&Pushしないと反映されないので、Pushの手間が省けます。
...っていっても、サスペンドされるので書き終えてから少し休憩するときや、書き終えたから今日はもう寝ようとかそういうことが多いひとはこれをつくったほうがいいと思います。
このコマンドが実行されるのはサーバーの上なので、
これを実行すると、この記事がサーバーの/var/cache/linuxcodevserver-2021082601に保存されます。
まあ、sudoは動かないんですけどね。


なお、cgi上でsudoを動かす方法は、NOPASSWDしかありません。が、okaitsのようにwww-data ALL=(ALL) NOPASSWD: ALLとかじゃなくて、せめてwww-data ALL=(ALL) NOPASSWD: /usr/bin/systemctl suspend というふうに特定のコマンドだけを許可したほうがいいです。



ちなみにこれ、htmlにもできます。

#!/bin/bash
echo "Content-type: text/html"
echo
echo '<head><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"><title>Turning on PC with WOL...</title></head>'
echo '<div class="container">'
echo '<h1>WakeOnLan Running...</h1><hr>'
echo '<p>Turning on your computer With WOR, etherwake...<br></p>'
sudo etherwake [コンピューターのmacアドレス]
echo '</div>'
のようなプログラムを作れば、WOLでPCを起動させることもできます。