2016/07/30(土)さくらのレンタルサーバーにPHP7を導入

2016年12月14日からPHP7.1が使用できるようになったので、この作業をする必要は無くなりました。→さくらのレンタルサーバ PHP7.1 提供開始のお知らせ | さくらインターネット

さくらのレンタルサーバーにPHP7を導入

さくらのレンタルサーバーがなかなかPHP7に対応しないので自力でインストールしてみました。

注意:この方法でPHP7を導入した後は、自身の責任においてセキュリティーアップデート(最新版の再導入)をしてください。

事前準備

サーバー上でビルドするのでSSHでアクセスできるようにしておきます。

ライトプランではSSHが使えないので、telnet.cgiを使うなどしてCGI経由で作業します。

  • telnet.cgi
    • 他人に使われると非常に危険なので、アクセス制限しておき、作業後は削除してください。

PHP7のビルド

サーバーに負荷がかかるのでアクセスが少ない時間帯に実施した方が無難です。「<アカウント名>」は、自身のアカウント名に置き換えてください。

現時点の最新版のPHP7.0.9での手順になっています。

  1. 作業ディレクトリとインストール先にするディレクトリを作成。
    cd /home/<アカウント名>/
    mkdir usr work
    
  2. PHP7のダウンロードと展開
    cd work
    wget --trust-server-names http://jp2.php.net/get/php-7.0.9.tar.bz2/from/this/mirror
    tar jxvf php-7.0.9.tar.bz2
    
  3. 以下の内容のファイルを作成し、展開ディレクトリ(/home/<アカウント名>/work/php-7.0.9)内にアップロードしておきます。(長いのでスクリプトファイルにしただけなので、直接configureを実行しても大丈夫だと思います。)
    #!/bin/sh
    ./configure \
      --prefix=/home/<アカウント名>/usr \
      --with-config-file-path=/home/<アカウント名>/usr/etc \
      --enable-mbstring \
      --enable-zip \
      --enable-bcmath \
      --enable-pcntl \
      --enable-ftp \
      --enable-exif \
      --enable-calendar \
      --enable-sysvmsg \
      --enable-sysvsem \
      --enable-sysvshm \
      --enable-wddx \
      --with-curl \
      --with-mcrypt \
      --with-iconv \
      --with-gmp \
      --with-gd \
      --with-jpeg-dir=/usr/local \
      --with-png-dir=/usr/local \
      --with-zlib-dir=/usr/local \
      --with-freetype-dir=/home/<アカウント名>/local \
      --enable-gd-native-ttf \
      --enable-gd-jis-conv \
      --with-openssl \
      --with-gettext=/usr/local \
      --with-zlib=/usr \
      --with-bz2=/usr/local \
      --with-mysqli \
      --with-pdo-mysql
    
  4. configureを実行
    cd php-7.0.9
    sh ./conf.sh
    
  5. ビルド、テスト、インストールを実行
    make
    make test
    make install
    
    • かなり時間がかかります。(特にテスト。)
    • ここで生成される /home/<アカウント名>/usr/bin/php-cgi が必要なファイルです。
参考:コマンド実行時の出力
  • ./conf.sh 実行時
    Generating files
    configure: creating ./config.status
    creating main/internal_functions.c
    creating main/internal_functions_cli.c
    +--------------------------------------------------------------------+
    | License:                                                           |
    | This software is subject to the PHP License, available in this     |
    | distribution in the file LICENSE.  By continuing this installation |
    | process, you are bound by the terms of this license agreement.     |
    | If you do not agree with the terms of this license, you must abort |
    | the installation process at this point.                            |
    +--------------------------------------------------------------------+
    
    Thank you for using PHP.
    
    config.status: creating php7.spec
    config.status: creating main/build-defs.h
    config.status: creating scripts/phpize
    config.status: creating scripts/man1/phpize.1
    config.status: creating scripts/php-config
    config.status: creating scripts/man1/php-config.1
    config.status: creating sapi/cli/php.1
    config.status: creating sapi/cgi/php-cgi.1
    config.status: creating ext/phar/phar.1
    config.status: creating ext/phar/phar.phar.1
    config.status: creating main/php_config.h
    config.status: executing default commands
    
  • make 実行時
    Generating phar.php
    Generating phar.phar
    PEAR package PHP_Archive not installed: generated phar will require PHP's phar extension be enabled.
    directorytreeiterator.inc
    pharcommand.inc
    directorygraphiterator.inc
    invertedregexiterator.inc
    clicommand.inc
    phar.inc
    
    Build complete.
    Don't forget to run 'make test'.
    
  • make test 実行時(failedがありますがPukiWikiを動かすだけなら問題はなさそうでした。)
    =====================================================================
    TEST RESULT SUMMARY
    ---------------------------------------------------------------------
    Exts skipped    :   27
    Exts tested     :   48
    ---------------------------------------------------------------------
    
    Number of tests : 14565             11252
    Tests skipped   : 3313 ( 22.7%) --------
    Tests warned    :    6 (  0.0%) (  0.1%)
    Tests failed    :   43 (  0.3%) (  0.4%)
    Expected fail   :   39 (  0.3%) (  0.3%)
    Tests passed    : 11164 ( 76.6%) ( 99.2%)
    ---------------------------------------------------------------------
    Time taken      :  790 seconds
    =====================================================================
    
    =====================================================================
    EXPECTED FAILED TEST SUMMARY
    ---------------------------------------------------------------------
    Test open_basedir configuration [tests/security/open_basedir_linkinfo.phpt]  XFAIL REASON: BUG: open_basedir cannot delete symlink to prohibited file. See also
    bugs 48111 and 52176.
    Inconsistencies when accessing protected members [Zend/tests/access_modifiers_008.phpt]  XFAIL REASON: Discussion: http://marc.info/?l=php-internals&m=120221184420957&w=2
    Inconsistencies when accessing protected members - 2 [Zend/tests/access_modifiers_009.phpt]  XFAIL REASON: Discussion: http://marc.info/?l=php-internals&m=120221184420957&w=2
    Bug #48770 (call_user_func_array() fails to call parent from inheriting class) [Zend/tests/bug48770.phpt]  XFAIL REASON: See Bug #48770
    Bug #48770 (call_user_func_array() fails to call parent from inheriting class) [Zend/tests/bug48770_2.phpt]  XFAIL REASON: See Bug #48770
    Bug #48770 (call_user_func_array() fails to call parent from inheriting class) [Zend/tests/bug48770_3.phpt]  XFAIL REASON: See Bug #48770
    bug #71428.1: inheritance with null default values [Zend/tests/bug71428.1.phpt]  XFAIL REASON: This is a BC break
    bug #71428: Validation type inheritance with = NULL [Zend/tests/bug71428.3.phpt]  XFAIL REASON: This is a BC break
    Initial value of static var in method depends on the include time of the class definition [Zend/tests/method_static_var.phpt]  XFAIL REASON: Maybe not a bug
    Bug #70228 (memleak if return in finally block) [Zend/tests/try/bug70228.phpt]  XFAIL REASON: See https://bugs.php.net/bug.php?id=70228
    DateTime::add() -- fall type2 type3 [ext/date/tests/DateTime_add-fall-type2-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::add() -- fall type3 type2 [ext/date/tests/DateTime_add-fall-type3-type2.phpt]  XFAIL REASON: Various bugs exist
    DateTime::add() -- fall type3 type3 [ext/date/tests/DateTime_add-fall-type3-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::add() -- spring type2 type3 [ext/date/tests/DateTime_add-spring-type2-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::add() -- spring type3 type2 [ext/date/tests/DateTime_add-spring-type3-type2.phpt]  XFAIL REASON: Various bugs exist
    DateTime::add() -- spring type3 type3 [ext/date/tests/DateTime_add-spring-type3-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::diff() -- fall type2 type3 [ext/date/tests/DateTime_diff-fall-type2-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::diff() -- fall type3 type2 [ext/date/tests/DateTime_diff-fall-type3-type2.phpt]  XFAIL REASON: Various bugs exist
    DateTime::diff() -- fall type3 type3 [ext/date/tests/DateTime_diff-fall-type3-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::diff() -- spring type2 type3 [ext/date/tests/DateTime_diff-spring-type2-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::diff() -- spring type3 type2 [ext/date/tests/DateTime_diff-spring-type3-type2.phpt]  XFAIL REASON: Various bugs exist
    DateTime::diff() -- spring type3 type3 [ext/date/tests/DateTime_diff-spring-type3-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::sub() -- fall type2 type3 [ext/date/tests/DateTime_sub-fall-type2-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::sub() -- fall type3 type2 [ext/date/tests/DateTime_sub-fall-type3-type2.phpt]  XFAIL REASON: Various bugs exist
    DateTime::sub() -- fall type3 type3 [ext/date/tests/DateTime_sub-fall-type3-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::sub() -- spring type2 type3 [ext/date/tests/DateTime_sub-spring-type2-type3.phpt]  XFAIL REASON: Various bugs exist
    DateTime::sub() -- spring type3 type2 [ext/date/tests/DateTime_sub-spring-type3-type2.phpt]  XFAIL REASON: Various bugs exist
    DateTime::sub() -- spring type3 type3 [ext/date/tests/DateTime_sub-spring-type3-type3.phpt]  XFAIL REASON: Various bugs exist
    Bug #55407 (Impossible to prototype DateTime::createFromFormat) [ext/date/tests/bug55407.phpt]  XFAIL REASON: Bug #55407
    RFC: DateTime and Daylight Saving Time Transitions (zone type 3, bd2) [ext/date/tests/rfc-datetime_and_daylight_saving_time-type3-bd2.phpt]  XFAIL REASON: Still not quite right
    RFC: DateTime and Daylight Saving Time Transitions (zone type 3, fs) [ext/date/tests/rfc-datetime_and_daylight_saving_time-type3-fs.phpt]  XFAIL REASON: Still not quite right
    Bug #42718 (unsafe_raw filter not applied when configured as default filter) [ext/filter/tests/bug42718.phpt]  XFAIL REASON: FILTER_UNSAFE_RAW not applied when configured as default filter, even with flags
    Bug #67296 (filter_input doesn't validate variables) [ext/filter/tests/bug49184.phpt]  XFAIL REASON: See Bug #49184
    Bug #67167: filter_var(null,FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE) returns null [ext/filter/tests/bug67167.02.phpt]  XFAIL REASON: Requires php_zval_filter to not use convert_to_string for all filters.
    Phar: bug #69958: Segfault in Phar::convertToData on invalid file [ext/phar/tests/bug69958.phpt]  XFAIL REASON: Still has memory leaks, see https://bugs.php.net/bug.php?id=70005
    Bug #69111 Crash in SessionHandler::read() [ext/session/tests/bug69111.phpt]  XFAIL REASON: It is still a leak
    Test basic function : variation3 use_trans_sid [ext/session/tests/session_basic3.phpt]  XFAIL REASON: Waiting url_scanner_ex.re fix. https://bugs.php.net/bug.php?id=68970
    Bug #70219 Use after free vulnerability in session deserializer [ext/standard/tests/serialize/bug70219.phpt]  XFAIL REASON: Unfinished merge, needs fix.
    Bug #70470 (Built-in server truncates headers spanning over TCP packets) [sapi/cli/tests/bug70470.phpt]  XFAIL REASON: bug is not fixed yet
    =====================================================================
    
    =====================================================================
    FAILED TEST SUMMARY
    ---------------------------------------------------------------------
    rfc1867 max_file_uploads - empty files shouldn't count (debug version) [tests/basic/rfc1867_max_file_uploads_empty_files_debug.phpt]
    Bug #30638 (localeconv returns wrong LC_NUMERIC settings) (ok to fail on MacOS X) [tests/lang/bug30638.phpt]
    Bug #60282 (Segfault when using ob_gzhandler() with open buffers) [tests/output/bug60282.phpt]
    unset() CV 7 (indirect unset() of global variable in import_request_variables()) [Zend/tests/unset_cv07.phpt]
    Font charmap order is deterministic based on order in the font, use the selected encoding [ext/gd/tests/imagettftext_charmap_order.phpt]
    Gettext basic test with en_US locale that should be on nearly every system [ext/gettext/tests/gettext_basic-enus.phpt]
    Test if bindtextdomain() returns string id if no directory path is set(if directory path is 'null') [ext/gettext/tests/gettext_bindtextdomain-cwd.phpt]
    Test dcgettext() functionality [ext/gettext/tests/gettext_dcgettext.phpt]
    Test dgettext() functionality [ext/gettext/tests/gettext_dgettext.phpt]
    Test if dngettext() returns the correct translations (optionally plural). [ext/gettext/tests/gettext_dngettext-plural.phpt]
    Test ngettext() functionality [ext/gettext/tests/gettext_ngettext.phpt]
    mb_http_input() [ext/mbstring/tests/mb_http_input.phpt]
    pcntl_wait() and rusage [ext/pcntl/tests/pcntl_wait_rusage1.phpt]
    pcntl_waitpid() and rusage [ext/pcntl/tests/pcntl_waitpid_rusage1.phpt]
    Phar: url stat [ext/phar/tests/020.phpt]
    Phar: stream stat [ext/phar/tests/021.phpt]
    Test for bug 52013 about Phar::decompressFiles(). [ext/phar/tests/bug52013.phpt]
    Phar front controller mime type extension is not a string [cache_list] [ext/phar/tests/cache_list/frontcontroller11.phpt]
    Phar front controller mime type extension is not a string [ext/phar/tests/frontcontroller11.phpt]
    Phar: phpinfo display 4 [ext/phar/tests/phpinfo_004.phpt]
    Phar front controller mime type extension is not a string tar-based [ext/phar/tests/tar/frontcontroller11.phar.phpt]
    Phar front controller mime type extension is not a string zip-based [ext/phar/tests/zip/frontcontroller11.phar.phpt]
    Test fileperms() & chmod() functions: usage variation - misc. perms [ext/standard/tests/file/006_variation2.phpt]
    chmod() basic functionality [ext/standard/tests/file/chmod_basic.phpt]
    Test chmod() function : second parameter variation [ext/standard/tests/file/chmod_variation4.phpt]
    Userstream unlink, rename, mkdir, rmdir, and url_stat. [ext/standard/tests/file/userwrapper.phpt]
    import_request_variables() tests [ext/standard/tests/general_functions/import_request.phpt]
    import_request_variables() test (overwrite super-globals) [ext/standard/tests/general_functions/import_request1.phpt]
    import_request_variables() test (numeric keys) [ext/standard/tests/general_functions/import_request2.phpt]
    import_request_variables() test (numeric keys, different order) [ext/standard/tests/general_functions/import_request3.phpt]
    Test get_browser() function : error functionality [ext/standard/tests/misc/get_browser_error.phpt]
    mixed stream_socket_enable_crypto(resource $stream , bool $enable [, int $crypto_type [, resource $session_stream ]] ) ; [ext/standard/tests/streams/stream_socket_enable_crypto.phpt]
    Test basename() function : usage variations with invalid paths [ext/standard/tests/strings/basename_invalid_path.phpt]
    Test setlocale() function : usage variations - Setting all available locales in the platform [ext/standard/tests/strings/setlocale_variation2.phpt]
    Test strptime() function : basic functionality [ext/standard/tests/time/strptime_basic.phpt]
    zlib.output_compression=1 with client not accepting compression [ext/zlib/tests/008.phpt]
    Bug #55544 (ob_gzhandler always conflicts with zlib.output_compression) [ext/zlib/tests/bug55544-win.phpt]
    checks zlib compression output size is always the same [ext/zlib/tests/bug60761.phpt]
    bug #61443 [ext/zlib/tests/bug61443.phpt]
    bug #61820 using ob_gzhandler will complain about headers already sent when no compression [ext/zlib/tests/bug61820.phpt]
    Bug #65391 (Unable to send vary header user-agent when ob_start('ob_gzhandler') is called) [ext/zlib/tests/bug65391.phpt]
    apache_request_headers() stack overflow. [sapi/cgi/tests/apache_request_headers.phpt]
    Bug #69487 (SAPI may truncate POST data) [sapi/tests/bug69487.phpt]
    =====================================================================
    
    =====================================================================
    WARNED TEST SUMMARY
    ---------------------------------------------------------------------
    Temporary leak on exception [Zend/tests/temporary_cleaning_001.phpt] (warn: XFAIL section but test passes)
    Fundamental memory leak test on temporaries [Zend/tests/temporary_cleaning_003.phpt] (warn: XFAIL section but test passes)
    Temporary leak with switch [Zend/tests/temporary_cleaning_004.phpt] (warn: XFAIL section but test passes)
    Temporary leak with foreach [Zend/tests/temporary_cleaning_005.phpt] (warn: XFAIL section but test passes)
    Exception after separation during indirect write to fcall result [Zend/tests/temporary_cleaning_006.phpt] (warn: XFAIL section but test passes)
    Bug #70172 - Use After Free Vulnerability in unserialize() [ext/standard/tests/serialize/bug70172_2.phpt] (warn: XFAIL section but test passes)
    =====================================================================
    
    You may have found a problem in PHP.
    This report can be automatically sent to the PHP QA team at
    http://qa.php.net/reports and http://news.php.net/php.qa.reports
    This gives us a better understanding of PHP's behavior.
    If you don't want to send the report immediately you can choose
    option "s" to save it.	You can then email it to qa-reports@lists.php.net later.
    Do you want to send this report now? [Yns]: 
    Please enter your email address.
    (Your address will be mangled so that it will not go out on any
    mailinglist in plain text): 
    Posting to http://qa.php.net/buildtest-process.php
    
  • make install 実行時
    Installing shared extensions:     /home/<アカウント名>/usr/lib/php/extensions/no-debug-non-zts-20151012/
    Installing PHP CLI binary:        /home/<アカウント名>/usr/bin/
    Installing PHP CLI man page:      /home/<アカウント名>/usr/php/man/man1/
    Installing phpdbg binary:         /home/<アカウント名>/usr/bin/
    Installing phpdbg man page:       /home/<アカウント名>/usr/php/man/man1/
    Installing PHP CGI binary:        /home/<アカウント名>/usr/bin/
    Installing PHP CGI man page:      /home/<アカウント名>/usr/php/man/man1/
    Installing build environment:     /home/<アカウント名>/usr/lib/php/build/
    Installing header files:           /home/<アカウント名>/usr/include/php/
    Installing helper programs:       /home/<アカウント名>/usr/bin/
      program: phpize
      program: php-config
    Installing man pages:             /home/<アカウント名>/usr/php/man/man1/
      page: phpize.1
      page: php-config.1
    Installing PEAR environment:      /home/<アカウント名>/usr/lib/php/
    /home/<アカウント名>/work/php-7.0.9/build/shtool install -c ext/phar/phar.phar /home/<アカウント名>/usr/bin
    ln -s -f phar.phar /home/<アカウント名>/usr/bin/phar
    Installing PDO headers:           /home/<アカウント名>/usr/include/php/ext/pdo/
    

PHP7の設定

  1. PHP7実行ファイルを公開ディレクトリにコピー。どこでも良いのですが、今回はwww/cgi-binにコピーします。
    cp /home/<アカウント名>/usr/bin/php-cgi /home/<アカウント名>/www/cgi-bin/php7.cgi
    
  2. phpスクリプトを設置するディレクトリの.htaccessに以下の記述を追加します。
    Action php7-script /cgi-bin/php7.cgi
    <FilesMatch "\.php$">
    	SetHandler php7-script
    </FilesMatch>
    
  3. php.iniの設置場所は以下になるので、必要に応じて設置します。
    • /home/<アカウント名>/usr/etc/php.ini

PHP7導入の効果

ECO-Wiki (acronia)のCPU負荷はほぼ半分になりました。

  • 4/30にPHP7導入
    php7_resource.png

追記: gzip圧縮するときの注意点

phpの出力をgzip圧縮したい場合は、PHP7実行ファイルを設置したディレクトリ(上記例だとwww/cgi-bin)に、以下の.htaccessを設置します。phpスクリプトと同じディレクトリの.htaccessではうまくいきませんでした。

<FilesMatch "\.cgi$">
	SetOutputFilter DEFLATE

	BrowserMatch ^Mozilla/4\.0[678] no-gzip
	BrowserMatch ^Mozilla/4 gzip-only-text/html
	BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

	AddOutputFilterByType DEFLATE text/html
</FilesMatch>

※text/htmlのみ圧縮。

参考ページ