シェルスクリプトで サーバ構築 自動化 研修コースに参加してみた
今回参加したコースは シェルスクリプトでサーバ構築自動化 です。
まっさらなサーバから Web サーバを構築するとなると、そもそもの Linux のユーザの設定、ホスト名の設定やネットワークの設定、 Apache のインストールと設定など、やることがたくさんありますよね。しかも、それぞれ間違えてはいけないので、ドキュメントを確認しつつ、ドキドキしながら作業することになりがちです。
そこで、作業を自動化して簡単かつ確実にしてしまいましょう、というのがこのコースです。インフラをコードで管理する Infrastructure as Code ( IaC ) の第一歩ですね。
今回はシェルスクリプトを使って Web サーバを自動構築します。その中で使われている「ヒトが関与しない」テクニックを色々と教えてもらいました。
なお、このコースは従来、教室で実施されていたところ、緊急事態宣言の再発令により、急遽オンラインで開催されました。これにともなって、講師の新谷さんのご厚意で、クラウドでサーバ( Linux )を立て、 Web ブラウザでコンソールを表示し、コマンドを実行する環境が用意されました。
では、どのような内容だったのか、レポートします!
もくじ
コース情報
想定している受講者 |
|
---|---|
受講目標 |
|
講師紹介
このコースで登壇されたのはインフラ系ではお馴染みの 新谷 泰英さん です。
どうすれば技術を身につけられるか、理解できるか、研究しつづけるインフラ系の人気トレーナー
自動構築するサーバとサンプルスクリプト
演習に先だって、構築するサーバとその構築手順、実行環境、用意頂いたサンプルのシェルスクリプトファイルを紹介頂きました。
-
構築するサーバと構築手順
- CentOS 7 がインストールされている状態からスタート
- CentOS 7 の設定
- Apache のインストールと設定
- MariaDB のインストールと設定
- WordPress のインストールと設定
なお今回のスクリプトのファイルは、見通しが悪くなるものの、エラーが見つけやすいよう 1 つのファイルで完結するようにします。
-
実行環境
- 新谷さんに用意いただいたサーバで実行
- AWS ( EC2 Linux ) 上に Docker を構築
- Linux にログインするとコンテナが展開
exit
するとコンテナが消える
- わざと改善点を残している
実行環境で行う作業で何かミスったら、 exit -> 再ログインすると、新しいコンテナが立ち上がるので、とっても演習しやすい環境でした。
どんな仕組みで動いてるんでしょうか。
サンプルを実行
本来であれば ftp/scp などでファイル転送するのですが、今回は練習ということもあり、予め実行環境にサンプルのシェルスクリプトファイルがある状態で、実行してみます。
# 実行権限の確認
if [ $UID -ne 0 ]; then
echo -e "** 実行エラー **\nroot権限で実行してください。\n"
return 2> /dev/null
exit
fi
# 設定ファイルバックアップ用のタイムスタンプ用意
TIMESTAMP=$(date "+%Y-%m-%d_%H-%M-%S")
# ホスト名設定、タイムゾーン設定
hostnamectl set-hostname web1.example.co.jp
timedatectl set-timezone Asia/Tokyo
#ネットワーク設定
#nmcli c mod enp0s3 connection.autoconnect yes
#nmcli c mod enp0s3 ipv4.method manual ipv4.addresses 10.10.10.2/24 ipv4.gateway 10.10.10.1
#nmcli c mod enp0s3 ipv4.dns 8.8.8.8,8.8.4.4
#nmcli c down enp0s3 && nmcli c up enp0s3
# F/W設定
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --reload
# グループ、ユーザーの作成
groupadd webadmin
for name in webuser1 webuser2 webuser3
do
useradd -g webadmin $name
echo 'P@ssw0rd' | passwd --stdin $name
done
# sshdの設定
sed -i".${TIMESTAMP}.bak" -e "s/^#UseDNS yes/UseDNS no/" /etc/ssh/sshd_config
systemctl restart sshd
# Apacheインストール
yum -y install \
httpd \
php \
php-gd \
php-mysql \
php-mbstring \
php-pdo
# httpd.confの設定変更
sed -i".${TIMESTAMP}.bak" -e "/<Directory \/>/,/<\/Directory>/ s/AllowOverride none/AllowOverride all/" /etc/httpd/conf/httpd.conf
sed -i -e "s/#ServerName www\.example\.com:80/ServerName $(hostname):80/" /etc/httpd/conf/httpd.conf
# php.iniの設定変更
sed -i".${TIMESTAMP}.bak" -e "s/^upload_max_filesize = .*M/upload_max_filesize = 10M/" /etc/php.ini
sed -i -e "s|^;date.timezone.*$|date.timezone = Asia/Tokyo|" /etc/php.ini
systemctl start httpd
systemctl enable httpd
# HTMLファイルの作成
cat <<- EOT > /var/www/html/index.html
<html>
<head>
<title>test page</title>
</head>
<body>
This is a test page.
</body>
</html>
EOT
# MariaDBのインストール
yum -y install mariadb-server
sed -i."${TIMESTAMP}.bak" -e "$ a \[mysql\]" /etc/my.cnf
sed -i -e "$ a default-character-set=utf8" /etc/my.cnf
systemctl start mariadb
systemctl enable mariadb
# WordPress用のデータベース作成
mysqladmin -u root password 'P@ssw0rd'
mysql -u root -pP@ssw0rd <<- EOT
create database wordpress;
exit
EOT
# WordPressのインストール
curl -O https://ja.wordpress.org/wordpress-5.1.1-ja.tar.gz
tar xvfz wordpress-5.1.1-ja.tar.gz
cp -r wordpress /var/www/html/wp
rm -Rf wordpress
rm -f wordpress-5.1.1-ja.tar.gz
chown -R apache.apache /var/www/html/wp
chcon -t httpd_sys_rw_content_t /var/www/html/wp/
# SELinuxの設定(Webアプリケーションからのメール送信許可)
setsebool -P httpd_can_sendmail 1
では、実行してみます。
# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
# cd ~
# cp /mnt/*sh .
# sh autosetup.sh
Changing password for user webuser1.
passwd: all authentication tokens updated successfully.
Changing password for user webuser2.
:
: (中略)
:
sed: can't read /etc/ssh/sshd_config: No such file or directory
Loaded plugins: fastestmirror, ovl
Determining fastest mirrors
* base: d36uatko69830t.cloudfront.net
* extras: d36uatko69830t.cloudfront.net
* updates: d36uatko69830t.cloudfront.net
base | 3.6 kB 00:00:00
extras | 2.9 kB 00:00:00
updates | 2.9 kB 00:00:00
(1/4): base/7/x86_64/group_gz | 153 kB 00:00:00
(2/4): extras/7/x86_64/primary_db | 222 kB 00:00:00
(3/4): updates/7/x86_64/primary_db | 4.7 MB 00:00:00
(4/4): base/7/x86_64/primary_db 46% [======================= ] 9.8 kB/s | 5.2 MB 00:10:17 ETA
:
:
画面の都合上、途中で切っていますが、無事に自動構築されました。
ということで、確認してみます。
# cd /etc/httpd/conf
# diff httpd.conf httpd.conf.2021-01-15_05-50-00.bak
95c95
< ServerName 01b8945b4980:80
> #ServerName www.example.com:80
103c103
< AllowOverride all
---
> AllowOverride none
```
# httpd
# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 11840 2960 pts/0 Ss 05:29 0:00 /bin/bash
root 203 0.0 1.0 433756 21672 ? Ss 06:11 0:00 httpd
apache 205 0.0 0.6 433756 12676 ? S 06:11 0:00 httpd
apache 206 0.0 0.6 433756 12676 ? S 06:11 0:00 httpd
apache 207 0.0 0.6 433756 12676 ? S 06:11 0:00 httpd
apache 208 0.0 0.6 433756 12676 ? S 06:11 0:00 httpd
apache 209 0.0 0.6 433756 12676 ? S 06:11 0:00 httpd
root 210 0.0 0.1 51744 3532 pts/0 R+ 06:11 0:00 ps aux
# curl http://localhost/
<html>
<head>
<title>test page</title>
</head>
<body>
This is a test page.
</body>
</html>
diff コマンドでバックアップ用の conf ファイルが新しく生成されているか、 localhost にアクセスしてみるなど、様々に確認して、無事構築されていました(設定ファイルは普通 Git などでバージョン管理しますが、今回はわかりやすさ重視です)。
シェルスクリプトで自動化するときのコツとルール
ここから、サンプルのシェルスクリプトについて解説です。
- 処理中に入力が求められないようにする
- eg.
yum -y install wget
- eg.
#! /bin/bash
で実行する環境を書いておく- bin ディレクトリにある bash で実行するという意味
- コメントは
ll #コメント
とコマンドの間にスペースを入れる - 順次・繰り返し・分岐が書ける
# グループ、ユーザーの作成
groupadd webadmin
for name in webuser1 webuser2 webuser3
do
useradd -g webadmin $name
echo 'P@ssw0rd' | passwd --stdin $name
done
ちなみに「パスワードは絶対こんなものにはしません」とのことでした。
# 実行権限の確認
if [ $UID -ne 0 ];
then
echo -e "** 実行エラー **\nroot権限で実行してください。\n"
return 2> /dev/null
exit
fi
なお、こういった繰り返しや分岐など基本的なシェルスクリプトの書き方は「別コースの シェルスクリプト入門 でぜひ!!」とのことでした。
シェルスクリプトで自動化するときのテクニック
ここからはサンプルで使っているテクニックの紹介です。
新谷さんからは「いくつも知っている状態が一番良いので、いろいろ引き出しを増やしましょう」とアドバイスされました。
設定ファイルのテクニック
例えば、設定ファイルのテクニックです。ちなみに、このあとのテクニックを使わずとも、予め用意したファイルを上書きコピーするコマンドを自動化すればできます。
- vi エディタでの手打ちは自動化出来ない
- sed / awk / grep を使おう (テキスト処理でよく使う)
sed (セド stream editor の略) を使う
- 文字列置換や行抽出、削除などのテキスト操作ライブラリ
- 設定ファイルの編集でよく使われる
- オプションを付けなければファイルを表示するだけ
- まずはオプションなしで実行してみてからオプションをつけよう
簡単な例で sed コマンドを打ってみましょう。
$ echo panasonic | sed -e s/a/A/ # s で置き換え
pAnasonic
$ echo panasonic | sed -e s/a/A/gi # g で該当するものすべてを書き換え i で大文字小文字関係なく置き換え
pAnAsonic
s
は文字列置き換えの意味です。その後に /
で区切って、変換前と変換後の文字列を書きます。
次に、 CentOS のバージョンが記されたファイル /etc/redhat-release で「 CentOS 」を書き換えて表示してみます。
$ sed -e "s/CentOS/Ubuntu/" /etc/redhat-release
Ubuntu Linux release 7.9.2009 (Core)
こうやって設定ファイルの一部を検出して置き換えていくわけです。
sed -i.bak -e "s/^#UseDNS yes/UseDNS no/" /etc/ssh/sshd_config
# -i オプションでファイルを書き換える
# .bak のような文字列を入れることも出来る(この例ではバックアップファイルが出来る)
# "s/^#UseDNS yes/UseDNS no/" が置換ルール
# /etc 以降はファイル名
ヒアドキュメント
- サンプル HTML ファイルの作成のように、複数行のテキストをファイルに書き出す
- シェルスクリプトの中に埋め込んでおいた文字列を出力
# HTMLファイルの作成
# <<- - でタブをOKにする
cat <<- EOT > /var/www/html/index.html
<html>
<head>
<title>test page</title>
</head>
<body>
This is a test page.
</body>
</html>
EOT # EOT は任意の文字列
サンプルにある他のテクニック
このあとは新谷さんがサンプルのシェルスクリプトを表示しながら、いろいろなテクニックや使い方を説明しました。
ここではその中の 1 つを紹介します。
if [ $UID -ne 0 ]; then # $UID はユーザ番号。一般なら 1000。 -ne は not equal (等しくない)
echo -e "** 実行エラー **\nroot権限で実行してください。\n"
return 2> /dev/null # 通常はただ return を書くとエラーが出るが、エラーメッセージをリダイレクトさせている
exit
fi
- シェルスクリプトを実行したのが root ではなく一般ユーザだったら、メッセージを表示してスクリプトを終了するというスクリプト
- return と exit でシェルスクリプトが終了する
- return が有効ならそこでスクリプトが終了する
- return が有効ではない場合、エラー
- 2 は終了コードで、処理に戻る
- > /dev/null でエラーメッセージをリダイレクト
- 改めて exit で終了する
自動化の練習方法
最後に新谷さんから今後の学習方法のアドバイスをいただきました。
- 「ゼロから書くより、興味ある部分や役に立ちそうなサンプルを見つけて、それをアレンジする」ことがオススメ
- 今回のサンプル autosetup.sh を題材にする場合
- 終了メッセージを出す
- 設定がうまくいったか検証する
- 二重実行できないよいうにする
- セットアップのフラグを作る、あるいはセットアップした内容の何かをフラグにする
- シェルスクリプトができると、 chef や puppet, Docker などの実行ファイルでも使える
まとめ
このコースでは用意されたシェルスクリプトをもとに自動化テクニックを解説いただきました。
Docker / Docker Compose などを使った自動構築や、 Jenkins など CI ツール、GitHub Actions などなど、ワークフローの自動化は急速に進んでいますが、今回のコースはその基礎となるものでした(その前に、私は Linux コマンドをググってるのを卒業せねば。。)。
また、今回は急遽、実地から切り替えて、オンラインで開催されましたが、受講者自身の PC の仮想環境を使わず、クラウドで自由に試せる実行環境はとても快適でした。加えて、講師から受講者側の進捗が見えなかったため、進捗が遅れ気味でもスクリプトをコピペで出来るよう、チャットで共有されたのも助かりました。さすが、新谷さんです。
DX には必須となる Infrastructure as Code に入門するにはうってつけのコースでした。
SEプラスにしかないコンテンツや、研修サービスの運営情報を発信しています。