最近、さくらのVPSやServersmanなど格安のVPSサービスや、Amazon Web ServicesやNiftyクラウドに代表されるクラウドサービスなどの台頭により、以前よりもサーバを使うことのハードルが下がりました。
そのためウェブ開発者がサーバの運用に関わる機会が増えていますが、ApacheやMySQL、PHP(Perl)などのいわゆるLAMP環境を作るには、意外と手間がかかることに気づかされます。
そこで、今回は1時間で出来るサーバセットアップを目標に、LAMP環境構築のチュートリアルとまとめました。
この手順においてはCentOSの基本的な設定が完了しているものとします。
参考:CentOSをサーバーとして活用するための基本的な設定(さくらインターネット創業日記)
CentOS 5.6へのバージョンアップ
今回の作業を行うにあたって、対象サーバがCentOS 5.5であったため、yum upgradeを実行して CentOS 5.6へバージョンアップしました。
すでにCentOS 5.6の場合には以下の作業は行わなくてもかまいません。
[root@ ~]# rpm -qa | grep centos-release
centos-release-notes-5.5-0
centos-release-5-5.el5.centos
[root@ ~]# yum upgrade
Loaded plugins: fastestmirror
Determining fastest mirrors
色々出てくる
Total download size: 162 M
Is this ok [y/N]: y ← 「y」と入力してリターン
Downloading Packages:
色々出てくる
Importing GPG key 0xE8562897 "CentOS-5 Key (CentOS 5 Official Signing Key)
[root@ ~]# rpm -qa | grep centos-release
centos-release-notes-5.6-0
centos-release-5-6.el5.centos.1 ← CentOS 5.6へとアップグレードされた
yumのリポジトリ追加
yumとは各種ソフトウェアをパッケージという単位にして、簡単にインストール・アンインストールするための仕組みのことです。
リポジトリを追加することによって、パッケージのダウンロード元サイトを増やし、インストールできるソフトウェアのバリエーションを増やすことが可能です。
標準のリポジトリではPHPの最新バージョンなどが用意されていませんので、今回は Fedora EPEL 、remi、RPMForge という3つのリポジトリを追加します。
はじめに、Fedora EPELのダウンロードを行います。
上記のファイルが無くなっている場合には、次のURLからepel-release-で始まるファイルを探してダウンロードして下さい。
http://download.fedora.redhat.com/pub/epel/5/x86_64/
次にremiのダウンロードを行います。
上記と同様に、ファイルが利用できない場合には、以下のURLからダウンロードして下さい。
http://rpms.famillecollet.com/el5.x86_64/
最後に、RPMForgeのダウンロードを行います。
上記と同様に、ファイルが利用できない場合には、以下のURLからダウンロードして下さい。
http://dag.wieers.com/rpm/packages/rpmforge-release/
それでは、3つのリポジトリを追加します。
[root@ ~]# rpm -Uvh epel-release-5-4.noarch.rpm remi-release-5-8.el5.remi.noarch.rpm rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm
warning: epel-release-5-4.noarch.rpm: Header V3 DSA signature: NOKEY, key ID 217521f6
warning: remi-release-5-8.el5.remi.noarch.rpm: Header V3 DSA signature: NOKEY, key ID 00f97f56
warning: rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm: Header V3 DSA signature: NOKEY, key ID 6b8d79e6
Preparing... ########################################### [100%]
1:epel-release ########################################### [ 33%]
2:remi-release ########################################### [ 67%]
3:rpmforge-release ########################################### [100%]
[root@ ~]#
リポジトリが追加できたら、それぞれのリポジトリをいったん無効化します。
具体的に言うと、設定ファイルのenabledという項目を0に変更し、yum実行時に明示的に指定されない限り、新たに追加したリポジトリが利用されないようにします。
ちなみに、remiはもともとenabled=0となっているので、Fedora EPELとRPMForgeのみviコマンドで編集します。
※意図せず、標準外のリポジトリ(今回追加したリポジトリ)が使われないための対策です。
vi /etc/yum.repos.d/epel.repo
name=Extra Packages for Enterprise Linux 5 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/5/$basearch
mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch
failovermethod=priority
enabled=0 ← 1を0に変更
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
vi /etc/yum.repos.d/rpmforge.repo
name = RHEL $releasever - RPMforge.net - dag
baseurl = http://apt.sw.be/redhat/el5/en/$basearch/rpmforge
mirrorlist = http://apt.sw.be/redhat/el5/en/mirrors-rpmforge
#mirrorlist = file:///etc/yum.repos.d/mirrors-rpmforge
enabled=0 ← 1を0に変更
protect = 0
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag
gpgcheck = 1
これでリポジトリの追加作業は完了です。
パッケージのインストール
それでは、パッケージのインストールを行います。
次のコマンド一発でインストールが開始され、途中で「y」を2回入力すれば、一気にLAMP環境を作られます。
今回は、追加したリポジトリが利用されるよう、--enablerepo オプションを付けています。
[root@ ~]# yum --enablerepo=remi,epel,rpmforge install httpd-devel php-devel php-pear mysql-server phpmyadmin
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
・・略・・
Total download size: 42 M
Is this ok [y/N]: y ← 「y」と入力してリターン
Downloading Packages:
・・略・・
warning: rpmts_HdrFromFdno: Header V3 DSA signature: NOKEY, key ID 00f97f56
remi/gpgkey | 1.3 kB 00:00
Importing GPG key 0x00F97F56 "Remi Collet
Is this ok [y/N]: y ← 「y」と入力してリターン
Running rpm_check_debug
今回インストールしたモジュールを一覧にしました。
モジュール | アーキテクチャ | バージョン | リポジトリ |
---|---|---|---|
apr-devel | x86_64 | 1.2.7-11 | base |
apr-util-devel | x86_64 | 1.2.7-11 | base |
cyrus-sasl-devel | x86_64 | 2.1.22-5 | base |
db4-devel | x86_64 | 4.3.29-10 | base |
expat-devel | x86_64 | 1.95.8-8.3 | base |
httpd | x86_64 | 2.2.3-45 | base |
httpd-devel | i386 | 2.2.3-45 | base |
httpd-devel | x86_64 | 2.2.3-45 | base |
libedit | x86_64 | 20090923-3.0_1 | rpmforge |
libmcrypt | x86_64 | 2.5.8-4 | extras |
libtool-ltdl | x86_64 | 1.5.22-7 | base |
mysql | x86_64 | 5.5.11-1 | remi |
mysql-libs | x86_64 | 5.5.11-1 | remi |
mysql-server | x86_64 | 5.5.11-1 | remi |
mysqlclient15 | x86_64 | 5.0.67-1 | remi |
openldap-devel | x86_64 | 2.3.43-12 | base |
perl-DBD-MySQL | x86_64 | 3.0007-2 | base |
perl-DBI | x86_64 | 1.52-2 | base |
php | x86_64 | 5.3.6-3 | remi |
php-cli | x86_64 | 5.3.6-3 | remi |
php-common | x86_64 | 5.3.6-3 | remi |
php-devel | x86_64 | 5.3.6-3 | remi |
php-mbstring | x86_64 | 5.3.6-3 | remi |
php-mcrypt | x86_64 | 5.3.6-3 | remi |
php-mysql | x86_64 | 5.3.6-3 | remi |
php-pdo | x86_64 | 5.3.6-3 | remi |
php-pear | noarch | 1.9.2-3 | remi |
phpmyadmin.noarch | 2.11.11.3-1 | rpmforge |
これで、インストールは完了です。
Apacheの設定 - モジュール編
それでは、Apacheの設定に移ります。
Apacheの設定は、/etc/httpd/conf/httpd.conf というファイルを編集して行いますが、モジュールの設定と、同時接続数の設定に分けて、順に見ていきましょう。
まずはモジュールの設定です。Apacheの場合、さまざまな機能を「モジュール」という形で用意しています。
モジュールを増やせばたくさんの機能を利用できますが、その反面メモリを大きく消費してしまうという問題があります。
CentOSのデフォルト状態では、ほぼ全てのモジュールが有効になっているため、必要以外のモジュールを除外する必要があります。
例えば、一切モジュールを消さないデフォルトの状態だと、1プロセスあたり5MB程度のメモリを消費していることが分かります。
apache 22523 0.0 0.4 257548 5036 ? S 12:27 0:00 /usr/sbin/httpd
これを適切に設定しなおすと、4MB程度まで減らせます。
1プロセスあたり1MB省略できれば、200プロセスで200MB削減できることになりますし、実際にリクエストを受け付けているプロセスの場合はさらに消費メモリの差が出ることになります。
apache 24715 0.0 0.4 161716 4228 ? S 19:46 0:00 /usr/sbin/httpd
とはいえ、どのモジュールが必要なのかが分かりにくいので、モジュールの一覧と、私の勝手な重要度をまとめました。
重要度は、◎、○、△、+、の4種類で分類しており、一覧にある重要度のタイトルをクリックすると、フィルターすることも可能です。
◎=必須
○=あったほうが良い
△=必要ならあればよい
+=必要性なし
モジュール名 | コメント | |
---|---|---|
mod_auth_basic | △ | ベーシック認証 |
mod_auth_digest | + | ダイジェスト認証 |
mod_authn_file | △ | 認証にテキストファイルを利用する いわゆる.htpasswdを使う場合は必要 |
mod_authn_alias | + | |
mod_authn_anon | + | 匿名ユーザを認証する |
mod_authn_dbm | + | 認証にDBMファイルを利用する |
mod_authn_default | + | |
mod_authz_host | ◎ | ホスト/IPアドレスでのアクセス制限 Orderや、Allow from ?? を使う場合は必須 |
mod_authz_user | △ | ユーザ名でのアクセス制限 |
mod_authz_owner | + | ファイル所有者でのアクセス制限 |
mod_authz_groupfile | + | グループでのアクセス制限を行う(テキストファイル) |
mod_authz_dbm | + | グループでのアクセス制限を行う(DBMファイル) |
mod_authz_default | + | |
mod_ldap | + | LDAP用の基本モジュール |
mod_authnz_ldap | + | LDAPでのアクセス制限 |
mod_include | △ | SSIを提供 SSIを利用する場合は有効にする |
mod_log_config | ◎ | ログ保存 アクセスログをとるためには必須 |
mod_logio | + | 送受信バイト数のログ保存(このモジュールがなければ保存できない) |
mod_env | △ | CGIやSSIでの環境変数を設定する 必要なければ無効でかまわない |
mod_ext_filter | + | データ返送時に外部プログラムを経由させる |
mod_mime_magic | + | ファイルの内容をベースにMIMEタイプ決定 |
mod_expires | + | Expireヘッダをセットする |
mod_deflate | + | データ返送時に圧縮する |
mod_headers | △ | リクエスト、レスポンスヘッダを制御する 必要なければ無効でかまわない |
mod_usertrack | + | クッキーでユーザ追跡を行う |
mod_setenvif | ◎ | 環境変数の制御を行う 無効でもかまわないが、標準の設定ファイルで利用されており、有効にするのが無難 |
mod_mime | ◎ | 拡張子をベースにMIMEタイプを決定 |
mod_dav | + | WebDAVを提供 |
mod_status | ○ | /server-statusにてサーバ状態を表示する(URLは変更可能) |
mod_autoindex | △ | ディレクトリへのアクセス時にファイル一覧を作成する |
mod_info | △ | /server-infoにてサーバ設定を表示する(URLは変更可能) |
mod_dav_fs | + | WebDAVを提供 |
mod_vhost_alias | + | バーチャルホストを簡単に生成 |
mod_negotiation | ◎ | クライアントに適したファイルを自動判別する(.jaなど) |
mod_dir | ◎ | ディレクトリの取り扱いを行う(index.htmlの取り扱いなど) |
mod_actions | + | 特定の拡張子へのリクエストに応じてCGIを実行する |
mod_speling | + | 大文字小文字を同じように扱えるようにする |
mod_userdir | △ | ユーザのホームディレクトにアクセスできるようにする(チルダ形式など) |
mod_alias | ◎ | AliasやRedirectを利用できるようにする |
mod_rewrite | △ | Rewrite機能を提供する |
mod_proxy | △ | Proxyを提供する |
mod_proxy_balancer | △ | Proxy時に負荷分散機能を提供 |
mod_proxy_ftp | + | Proxy時にFTP接続機能を提供 |
mod_proxy_http | △ | Proxy時にHTTP接続機能を提供 |
mod_proxy_connect | + | Proxy時にCONNECT機能を提供 |
mod_cache | + | キャッシュを提供 |
mod_suexec | △ | suexecを提供 |
mod_disk_cache | + | cache_moduleにおいて、ディスクキャッシュを提供 |
mod_file_cache | + | 静的ファイルをメモリにキャッシュさせる |
mod_mem_cache | + | cache_moduleにおいて、メモリキャッシュを提供 |
mod_cgi | △ | CGIを提供 |
mod_version | ○ | クライアントへのレスポンスにApacheバージョンを挿入する |
※注意点
以下のモジュールを無効にすると、標準の設定ファイル(/etc/httpd/conf/httpd.conf)のまま起動するとエラーとなります。
- mod_authz_hostを無効にした場合には、OrderやAllowなどの項目(例えば332行目など)をコメントアウトする必要があります
- mod_proxyを無効にした場合には、以下ようにコマンドを実行し拡張設定ファイルを無効化する必要があります
- mod_autoindexを無効にした場合には、IndexOptionsから始まる関連項目(例えば592行目?657行目)を全てコメントアウトする必要があります
もしくは以下のとおり、<IfModule>で括ってしまう方法もあります
vi /etc/httpd/conf/httpd.conf
IndexOptions FancyIndexing VersionSort NameWidth=* HTMLTable
・・略・・
IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
</IfModule>
ちなみに、私はいつも以下のモジュールを有効にしています。
なお、mod_autoindex と mod_proxy を無効化していますので、前述のとおり設定を変更しなければエラーとなって起動しません。
LoadModule log_config_module modules/mod_log_config.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule status_module modules/mod_status.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so
Apacheの設定 - 同時接続数編
それでは、Apacheの同時接続数の設定を見ていきましょう。
ここで基本を押さえておきたいのですが、Apacheにはpreforkとworkerという大きく分けると2つの方式があります。
preforkはサーバ1つ(1プロセス)で1つのリクエストを処理し、workerはサーバ1つで複数のリクエストを処理できます。
一見、workerのほうが良いように見えますが、workerはマルチスレッドで実装されていることから、ライブラリ全てがマルチスレッドに対応している必要があります。
ただ、PHPを使う場合にはライブラリ全てがマルチスレッド対応か否かを検証することは難しく、余計なトラブルを避けるためにもpreforkを利用するのが賢明であるといえます。
ということで、今回はpreforkを使う前提で説明を行います。
標準のhttpd.confでは、以下のように設定されています。
StartServers 8
MinSpareServers 5
MaxSpareServers 20
ServerLimit 256
MaxClients 256
MaxRequestsPerChild 4000
</IfModule>
これらを順に見てみましょう。
- StartServers Apache開始時に立ち上げておくべきサーバ数。
- MinSpareServers アイドル中のサーバ数の下限。アイドル中とは、リクエストに対して即座に対応できる状態(つまり処理していない)のこと。
- MaxSpareServers アイドル中のサーバ数の上限。
- ServerLimit 後述するMaxClientsに指定できる数字の上限を指定する。
- MaxClients サーバ数の上限。
- MaxRequestsPerChild 処理できるリクエストの上限数。
Apache起動直後は、ここで指定した数のサーバが立ち上がる。
ここで指定したサーバより少なくなった場合は、新たなサーバを立ち上げる。
この数値が小さすぎると、急激にアクセスが増えたときに、リクエストに受けきれなくなる。
ここで指定したサーバより多くなった場合は、余計なサーバを終了させる。
この数字が大きすぎると、アクセスが落ち着いている状態でもサーバが終了されず、メモリが無駄に消費されることになる。
MaxClientsを256より大きな数字にするとき以外は、特に変更の必要はない。
ここで指定した数以上のサーバは立ち上がらない。
処理したリクエストがここで指定した数を超えると、該当サーバは終了される。
文字ではなかなかピンと来ない方も多いと思うので、グラフでまとめてみました。
このグラフでは見やすくするため、MaxClients 30、StartServers 10、MinSpareServers 5、MaxSpareServers 20としています。
1 | 起動直後であり、StartServersで指定された10サーバが立ち上がっている |
2 | 10サーバが接続中でアイドル状態のサーバが0となったため、MinSpareServersに指定された5サーバが追加される |
3 | 20サーバが接続中で上記と同じくアイドル状態サーバが0となったため、さらに5サーバが追加される |
4 | アイドル状態のサーバが0になったものの、MaxClientsで指定された30サーバになったため、新規サーバは追加されない |
MaxClientsを超える数の接続がきたため、30の上限を超えるリクエストは、空きが出るまでまで待たされる | |
アイドル状態のサーバ数は5以上20以下であり、新たなサーバの起動や、余剰サーバの終了処理は行わない | |
11 | 30サーバがアイドル状態となったため、MaxSpareServersで指定された20サーバにすべく、10サーバが終了させられた |
それでは、実際にどのような数字を設定すればいいか、考えて見ましょう。
一番重要なのはMaxClientsです。これが決まれば、上記の法則を見て他の値も決定してください。
たくさんのリクエストを受け付けるためには、大きな数値にすればよいと考えられがちですが、メモリやCPU能力が十分でなければ、むしろパフォーマンスが低下します。
経験則では、PHPを稼動させるApacheは1サーバあたり10MBから30MB程度のメモリを消費します。
例えば、Apacheで利用するメモリ容量を500MB程度に抑えたければ、20から40程度の数値にしておくのが無難です。
以下の例は、MaxClientsが256のときと、20のときで、どのように挙動が変わるかをabで図ったものです。
MaxClientsが256の場合は、スワップを大きく消費しているほか、ロードアベレージも大きく上がっており、SSHのレスポンスについても非常に悪化していました。
それに対し20の場合は、それほど負荷の上昇は見られず、計測時間、秒間処理数、リクエストにかかる秒数の全てにおいて、改善していることが分かります。
要は、無理に同時に処理する数を増やすより、少々待たされる状態が出たとしてもサーバ能力を超えない範囲にしたほうが、結果としてレスポンスは良くなるということです。
サーバ負荷が高く、レスポンスが悪化した場合は、MaxClientsを増やすのではなく、減らすことをまず考えた方が賢明です。
MaxClients | スワップ | ロードアベレージ | 計測時間 | 秒間処理数 | リクエスト |
---|---|---|---|---|---|
256 | 859MB | 79.26 | 55.40秒 | 36.10/秒 | 2.73秒 |
20 | 11MB | 5.46 | 35.66秒 | 56.08/秒 | 1.74秒 |
1サーバあたりのメモリ使用量(ps結果のRSS)は10MB程度でしたので、100サーバだと1GB程度消費するのに対し、20サーバだと200MB程度で済みます。結局のところ、Apacheで使用する容量÷10MB?30MB程度で考えるのが良いでしょう。
参考までに、私が1GBメモリ、2コア程度のサーバ(さくらのVPS 1Gプラン相当)でいつも行っている設定は以下のような値です。
StartServers 10
MinSpareServers 5
MaxSpareServers 15
ServerLimit 256
MaxClients 40
MaxRequestsPerChild 1000
</IfModule>
Apacheの起動
Apacheを起動するには、serviceというコマンドを利用します。
以下のように打ち込んで、問題なければ正常に起動します。
Starting httpd: [ OK ]
なおエラーが出る場合には、モジュールを削ったときの設定ファイル変更を忘れている可能性があります。
設定ファイルの問題の際には、エラーメッセージとともに行番号が書かれていますので、再確認して下さい。
MySQLの設定と起動
それでは、MySQLの設定と起動を見てみましょう。
MySQLの設定については /etc/my.cnf を編集することで可能ですが、あらかじめ最低限の設定はされているので、ひとまず起動をして管理者パスワードの設定を行います。
MySQLを起動するには、serviceコマンドを利用します。
# service mysqld start
Initializing MySQL database: Installing MySQL system tables...
OK
Filling help tables...
OK
・・中略・・
[ OK ]
Starting mysqld: [ OK ]
無事に起動できれば、[ OK ] と表示されます。
次に設定を移ります。
設定には専用のスクリプトが用意されているので、そちらを利用します。
# /usr/bin/mysql_secure_installation
・・略・・
Enter current password for root (enter for none): ← デフォルトではパスワードが無いので、そのままリターン
OK, successfully used password, moving on...
Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.
Set root password? [Y/n] y ← 「y」と入力してリターン
New password: ← rootパスワードとして設定したい文字列を入力してリターン
Re-enter new password: ← もう一度入力してリターン
Password updated successfully!
Reloading privilege tables..
... Success!
By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.
Remove anonymous users? [Y/n] y ← 「y」と入力してリターン
... Success!
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
Disallow root login remotely? [Y/n] y ← 「y」と入力してリターン
... Success!
By default, MySQL comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
Remove test database and access to it? [Y/n] y ← 「y」と入力してリターン
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
Reload privilege tables now? [Y/n] y ← 「y」と入力してリターン
... Success!
Cleaning up...
All done! If you've completed all of the above steps, your MySQL
installation should now be secure.
Thanks for using MySQL!
これで、MySQLが利用できるようになりました。
phpmyadminの設定
ここまでで、Apache、PHP、MySQLの全てが利用可能になりました。
最後に、phpmyadminの設定を行いましょう。
まずは、phpmyadminの設定ファイルを変更します。
変更するのは、blowfish_secret という項目だけです。以下のようにご自身で決めたランダムな文字列を入れてください。
vi /usr/share/phpmyadmin/config.inc.php
次に接続元のIPアドレスを追加します。
以下のように、/etc/httpd/conf.d/phpmyadmin.conf を編集し、Allow from を追加します。
vi /etc/httpd/conf.d/phpmyadmin.conf
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
Allow from 59.106.??.??
</Directory>
設定ファイルの編集が終われば、Apacheに設定ファイルを再読み込みさせれば完了です。
Starting httpd: [ OK ]
ブラウザからアクセスをすると、無事phpmyadminの画面が表示されました。
ユーザ名に root と入力し、パスワードには先ほどの文字列を入力します。
自動起動設定と、再起動
これで、LAMP環境の設定がひとまず完了し、利用可能な状況となりました。
しかし、これで安心してはいけません。
再起動した場合には、ApacheもMySQLも自動で起動せず、アクセスが受け付けられない状況となります。
自動起動するかどうかを確認するためには、chkconfigコマンドを利用します。
3という項目がoffの場合には、再起動時にApacheやMySQLが自動起動されません。
httpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
mysqld 0:off 1:off 2:off 3:off 4:off 5:off 6:off
# chkconfig httpd on
# chkconfig mysqld on
# chkconfig --list|grep -E "httpd|mysql"
httpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
mysqld 0:off 1:off 2:on 3:on 4:on 5:on 6:off
#
これで再起動をすれば、全ての作業が完了です。
再起動しなくても問題ありませんが、再起動された時に自動で全てのソフトウェアが起動するかどうかを確かめるためにも、再起動を強くお勧めします。
時間としては1時間程度で済みましたでしょうか?
最近では、クラウドの機能が増えたことによりこういった作業を必要ないという人もいますが、ウェブ開発者のたしなみとして、これくらいはできるべきだと思います。
慣れれば10分くらいでできますし、数十台程度であれば平行で作業すれば30分もあれば出来ます。
ということで、皆さんもぜひがんばってチャレンジしてみてください。
なお皆さまからも「ここはこの方がいい!」とかあればぜひご指摘頂ければ幸いです。
コメントする