安装Drupal的系统需求, 需要web server, database, php.
本文以Drupal 7.28, Nginx 1.6, PostgrSQL 9.3.4, PHP 5.4为例写一下Drupal的部署.
不涉及任何优化, 例如使用fpm, 用unix sock连接效率会更高.
安装参考
一. nginx 安装, 本文选择使用rpm安装 :
首先要把nginx的源添加进来.
使用yum安装nginx
配置nginx, 可参考.
2. PostgreSQL 9.3.4 编译项
3. PostgreSQL 参数
4. 存储
# vi /etc/yum.repos.d/nginx.repo [nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/6/$basearch/ gpgcheck=0 enabled=1
AI 代码解读
使用yum安装nginx
# yum install -y nginx Dependencies Resolved ==================================================================================================================================== Package Arch Version Repository Size ==================================================================================================================================== Installing: nginx x86_64 1.6.0-1.el6.ngx nginx 335 k Transaction Summary ==================================================================================================================================== Install 1 Package(s) # rpm -ql nginx /etc/logrotate.d/nginx /etc/nginx /etc/nginx/conf.d /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/example_ssl.conf /etc/nginx/fastcgi_params /etc/nginx/koi-utf /etc/nginx/koi-win /etc/nginx/mime.types /etc/nginx/nginx.conf /etc/nginx/scgi_params /etc/nginx/uwsgi_params /etc/nginx/win-utf /etc/rc.d/init.d/nginx /etc/sysconfig/nginx /usr/sbin/nginx /usr/share/nginx /usr/share/nginx/html /usr/share/nginx/html/50x.html /usr/share/nginx/html/index.html /var/cache/nginx /var/log/nginx # id nginx uid=494(nginx) gid=490(nginx) groups=490(nginx)
AI 代码解读
配置nginx, 可参考.
# vi /etc/nginx/nginx.conf user nginx; worker_processes 4; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 2; #gzip on; include /etc/nginx/conf.d/*.conf; } # vi /etc/nginx/conf.d/default.conf server { listen 80; server_name _; #charset koi8-r; #access_log /var/log/nginx/log/host.access.log main; location / { root /opt/site/drupal; # drupal下载后重命名到这里. index index.php index.html index.htm; error_page 404 = @drupal; } location @drupal { rewrite ^(.*)$ /index.php?q=$1 last; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} location ~ \.php$ { root /opt/site/drupal; include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; # php-fpm的监听 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # service nginx start Starting nginx: [ OK ] # netstat -anp|grep nginx tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 10382/nginx
AI 代码解读
测试nginx服务是否正常 :

二. PostgreSQL的安装和配置, 简单的写一下, 使用9.3.4的源码安装. (假设服务器内存96G).
1. Linux 内核参数
vi /etc/sysctl.conf # add by digoal.zhou kernel.shmmni = 4096 kernel.sem = 50100 64128000 50100 1280 fs.file-max = 7672460 net.ipv4.ip_local_port_range = 9000 65000 net.core.rmem_default = 1048576 net.core.rmem_max = 4194304 net.core.wmem_default = 262144 net.core.wmem_max = 1048576 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_max_syn_backlog = 4096 net.core.netdev_max_backlog = 10000 fs.aio-max-nr = 1048576 net.ipv4.tcp_timestamps = 0 vm.overcommit_memory = 0 net.ipv4.tcp_keepalive_time = 60 net.ipv4.tcp_keepalive_intvl = 10 vi /etc/security/limits.conf # add by digoal.zhou * soft nofile 131072 * hard nofile 131072 * soft nproc 131072 * hard nproc 131072 * soft core unlimited * hard core unlimited * soft memlock 50000000 * hard memlock 50000000 vi /etc/security/limits.d/90-nproc.conf # 注释所有并添加 * soft nproc 131072 * hard nproc 131072 生效 sysctl -p
AI 代码解读
2. PostgreSQL 9.3.4 编译项
./configure '--with-perl' '--with-tcl' '--with-python' '--with-openssl' '--with-pam' '--with-ldap' '--with-libxml' '--with-libxslt' '--enable-thread-safety' '--with-blocksize=32' gmake world gmake install-world
AI 代码解读
3. PostgreSQL 参数
vi postgresql.conf listen_addresses = '0.0.0.0' # what IP address(es) to listen on; port = 5432 # (change requires restart) max_connections = 2000 # (change requires restart) superuser_reserved_connections = 13 # (change requires restart) unix_socket_directories = '.' # comma-separated list of directories unix_socket_permissions = 0700 # begin with 0 to use octal notation password_encryption = on tcp_keepalives_idle = 60 # TCP_KEEPIDLE, in seconds; tcp_keepalives_interval = 10 # TCP_KEEPINTVL, in seconds; tcp_keepalives_count = 10 # TCP_KEEPCNT; shared_buffers = 2048MB # min 128kB work_mem = 1024MB # min 64kB maintenance_work_mem = 1024MB # min 1MB shared_preload_libraries = 'pg_stat_statements' # (change requires restart) vacuum_cost_delay = 10 # 0-100 milliseconds vacuum_cost_limit = 10000 # 1-10000 credits bgwriter_delay = 10ms # 10-10000ms between rounds wal_level = hot_standby # minimal, archive, or hot_standby synchronous_commit = off # synchronization level; wal_buffers = 16384kB # min 32kB, -1 sets based on shared_buffers wal_writer_delay = 10ms # 1-10000 milliseconds checkpoint_segments = 128 # in logfile segments, min 1, 16MB each archive_mode = on # allows archiving to be done archive_command = '/bin/date' # command to use to archive a logfile segment max_wal_senders = 32 # max number of walsender processes wal_keep_segments = 512 # in logfile segments, 16MB each; 0 disables hot_standby = on # "on" allows queries during recovery max_standby_archive_delay = 300s # max delay before canceling queries max_standby_streaming_delay = 300s # max delay before canceling queries wal_receiver_status_interval = 1s # send replies at least this often hot_standby_feedback = on # send info from standby to prevent effective_cache_size = 96000MB log_destination = 'csvlog' # Valid values are combinations of logging_collector = on # Enable capturing of stderr and csvlog log_directory = 'pg_log' # directory where log files are written, log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern, log_file_mode = 0600 # creation mode for log files, log_truncate_on_rotation = on # If on, an existing log file with the log_rotation_age = 1d # Automatic rotation of logfiles will log_rotation_size = 10MB # Automatic rotation of logfiles will log_min_duration_statement = 1s # -1 is disabled, 0 logs all statements log_checkpoints = on log_connections = on log_disconnections = on log_error_verbosity = verbose # terse, default, or verbose messages log_statement = 'ddl' # none, ddl, mod, all log_timezone = 'PRC' track_activity_query_size = 4096 # (change requires restart) autovacuum = on # Enable autovacuum subprocess? 'on' log_autovacuum_min_duration = 0 # -1 disables, 0 logs all actions and datestyle = 'iso, mdy' timezone = 'PRC' lc_messages = 'C' # locale for system error message lc_monetary = 'C' # locale for monetary formatting lc_numeric = 'C' # locale for number formatting lc_time = 'C' # locale for time formatting default_text_search_config = 'pg_catalog.english' pg_stat_statements.max = 1000 pg_stat_statements.track = all pg_stat_statements.save = on 其他的全部注释掉. pg_hba.conf host all all 0.0.0.0/0 md5 生效 重启数据库
AI 代码解读
4. 存储
pg_xlog, 活跃表, 索引 等 分开到不同的块设备(底层也分开)存储.
5. 活跃表优化
下载这个插件安装
6. 请求跟踪, SQL优化
这些SQL 的执行计划
配置php, 参见 :
四. 安装Drupal 7.28
安装语言文件至drupal/profiles/standard/translations/
五. 创建数据库
测试连接 :
六. 配置drupal.
打开一个IE浏览器, 输入WEB SERVER的IP.
说明缺少php的gd模块和mbstring模块.
http://git.postgresql.org/gitweb/?p=pgfincore.git;a=summary mv pgfincore $PGSRC/contrib export PATH=$PGHOME/bin:$PATH 确保pg_config命令在当前路径 cd $PGSRC/contrib/pgfincore make clean make && make install psql dbname superuser create extension pgfincore; select * from pgfadvise_willneed('$sechema.活跃表'::regclass); select * from pgfadvise_willneed('$sechema.活跃索引'::regclass);
AI 代码解读
6. 请求跟踪, SQL优化
psql postgres postgres create extension pg_stat_statements; select pg_stat_statements_reset(); 执行应用压力测试. 完了后查询CPU耗时排前5的SQL. select query,calls,total_time,total_time/calls from pg_stat_statements order by 3 desc limit 5 offset 0;
AI 代码解读
这些SQL 的执行计划
explain $SQL;
看看有没有优化空间.
三. 安装PHP
yum install -y php php-xml php-fpm php-pgsql php-pdo php-common php-cli php-intl php-gd # rpm -qa|grep php php-pdo-5.4.30-1.el6.remi.x86_64 php-common-5.4.30-1.el6.remi.x86_64 php-5.4.30-1.el6.remi.x86_64 php-cli-5.4.30-1.el6.remi.x86_64 php-intl-5.4.30-1.el6.remi.x86_64 php-pgsql-5.4.30-1.el6.remi.x86_64 php-xml-5.4.30-1.el6.remi.x86_64 php-fpm-5.4.30-1.el6.remi.x86_64 # php -v PHP 5.4.30 (cli) (built: Jun 25 2014 15:27:51) Copyright (c) 1997-2014 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies 启动php-fpm服务, 默认监听9000端口.php配置变更的话, 需要重启这个服务来生效. [root@db-172-16-3-150 drupal]# service php-fpm start Starting php-fpm: [ OK ] [root@db-172-16-3-150 drupal]# netstat -anp|grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 14159/php-fpm
AI 代码解读
配置php, 参见 :
vi /etc/php.ini Recommended PHP configuration settings Setting: session.cache_limiter = nocache Setting: session.auto_start = 0 Setting: expose_php = off Reason: Shows current PHP version in all header requests, security disclosure, see here Example: X-Powered-By: PHP/5.3.8 Setting: allow_url_fopen = off Reason: This is a security issue: see here Setting: magic_quotes_gpc = off Reason: Forces quotes in variables - This feature has been deprecated as of PHP 5.3.0 and removed as of PHP 5.4.0. Setting: register_globals = off Reason: Security issue - having this enabled subjects PHP variables to input from any source: This feature has been deprecated as of PHP 5.3.0 and removed as of PHP 5.4.0. Setting: display_errors = Off Reason: Hides errors output to display (website) we want to send to log file instead.
AI 代码解读
四. 安装Drupal 7.28
下载drupal
wget http://ftp.drupal.org/files/projects/drupal-7.28.tar.gz tar -zxvf drupal-7.28.tar.gz # ll drupal-7.28 total 252 -rw-r--r-- 1 6226 6226 6604 May 8 12:05 authorize.php -rw-r--r-- 1 6226 6226 88691 May 8 12:05 CHANGELOG.txt -rw-r--r-- 1 6226 6226 1481 May 8 12:05 COPYRIGHT.txt -rw-r--r-- 1 6226 6226 720 May 8 12:05 cron.php drwxr-xr-x 4 6226 6226 4096 May 8 12:05 includes -rw-r--r-- 1 6226 6226 529 May 8 12:05 index.php -rw-r--r-- 1 6226 6226 1717 May 8 12:05 INSTALL.mysql.txt -rw-r--r-- 1 6226 6226 1874 May 8 12:05 INSTALL.pgsql.txt -rw-r--r-- 1 6226 6226 703 May 8 12:05 install.php -rw-r--r-- 1 6226 6226 1298 May 8 12:05 INSTALL.sqlite.txt -rw-r--r-- 1 6226 6226 17995 May 8 12:05 INSTALL.txt -rwxrwxrwx 1 6226 6226 18092 Nov 1 2013 LICENSE.txt -rw-r--r-- 1 6226 6226 8191 May 8 12:05 MAINTAINERS.txt drwxr-xr-x 4 6226 6226 4096 May 8 12:05 misc drwxr-xr-x 42 6226 6226 4096 May 8 12:05 modules drwxr-xr-x 5 6226 6226 4096 May 8 12:05 profiles -rw-r--r-- 1 6226 6226 5382 May 8 12:05 README.txt -rw-r--r-- 1 6226 6226 1561 May 8 12:05 robots.txt drwxr-xr-x 2 6226 6226 4096 May 8 12:05 scripts drwxr-xr-x 4 6226 6226 4096 May 8 12:05 sites drwxr-xr-x 7 6226 6226 4096 May 8 12:05 themes -rw-r--r-- 1 6226 6226 19986 May 8 12:05 update.php -rw-r--r-- 1 6226 6226 9642 May 8 12:05 UPGRADE.txt -rw-r--r-- 1 6226 6226 2178 May 8 12:05 web.config -rw-r--r-- 1 6226 6226 417 May 8 12:05 xmlrpc.php 创建站点目录, 和nginx配置的root一致. [root@db-172-16-3-150 ~]# mkdir /opt/site [root@db-172-16-3-150 ~]# mv /opt/soft_bak/drupal-7.28 /opt/site/drupal [root@db-172-16-3-150 ~]# chown -R nginx:nginx /opt/site/drupal
AI 代码解读
安装语言文件至drupal/profiles/standard/translations/
https://localize.drupal.org/translate/downloads [root@db-172-16-3-150 drupal]# cd /opt/site/drupal/profiles/standard/translations/ [root@db-172-16-3-150 translations]# ll total 4 -rw-r--r-- 1 nginx nginx 92 May 8 12:05 README.txt [root@db-172-16-3-150 translations]# wget http://ftp.drupal.org/files/translations/7.x/drupal/drupal-7.28.zh-hans.po
AI 代码解读
五. 创建数据库
digoal=# create role drupal nosuperuser login encrypted password 'drupal123'; CREATE ROLE pg93@db-172-16-3-150-> cd /ssd4/pg93 pg93@db-172-16-3-150-> mkdir tbs_drupal digoal=# create tablespace tbs_drupal location '/ssd4/pg93/tbs_drupal'; CREATE TABLESPACE digoal=# create database drupal728 with template template0 encoding 'UTF8' tablespace tbs_drupal; CREATE DATABASE digoal=# grant all on tablespace tbs_drupal to drupal; GRANT digoal=# grant all on database drupal728 to drupal; GRANT digoal=# \c drupal728 drupal You are now connected to database "drupal728" as user "drupal". drupal728=> create schema drupal; CREATE SCHEMA
AI 代码解读
测试连接 :
pg93@db-172-16-3-150-> psql -h 172.16.3.150 -p 5432 -U drupal drupal728 Password for user drupal: psql (9.3.3) Type "help" for help. drupal728=> \dn List of schemas Name | Owner --------+---------- drupal | drupal public | postgres (2 rows)
AI 代码解读
六. 配置drupal.
在浏览器运行install.php脚本前的配置.
[root@db-172-16-3-150 drupal]# cd /opt/site/drupal/ [root@db-172-16-3-150 drupal]# cp sites/default/default.settings.php sites/default/settings.php [root@db-172-16-3-150 drupal]# chmod a+w sites/default/settings.php [root@db-172-16-3-150 drupal]# chmod a+w sites/default
AI 代码解读
打开一个IE浏览器, 输入WEB SERVER的IP.



安装即可
现在要重启php-fpm服务来生效新安装的php模块.
配置方法很多, 随便选一种.
接下来安装过程出错, 违反非空约束如下,
非空约束错误, 从postgresql查看日志 :
这个错误可以直接点击the error page, 跳到手工处理配置界面.
现在可以打开drupal了.
配置自动开启这些服务.
[参考]
# yum install -y php-gd php-mbstring
AI 代码解读
查看GD库是否启用, 现在不需要配置在php.ini, 这些配置在/etc/php.d中:
# less /etc/php.ini
;;;;
; Note: packaged extension modules are now loaded via the .ini files
; found in the directory /etc/php.d; these are loaded by default.
;;;;
查看当前加载的配置文件.
# php --ini Configuration File (php.ini) Path: /etc Loaded Configuration File: /etc/php.ini Scan for additional .ini files in: /etc/php.d Additional .ini files parsed: /etc/php.d/curl.ini, /etc/php.d/dom.ini, /etc/php.d/fileinfo.ini, /etc/php.d/gd.ini, /etc/php.d/intl.ini, /etc/php.d/json.ini, /etc/php.d/mbstring.ini, /etc/php.d/pdo.ini, /etc/php.d/pdo_pgsql.ini, /etc/php.d/pdo_sqlite.ini, /etc/php.d/pgsql.ini, /etc/php.d/phar.ini, /etc/php.d/sqlite3.ini, /etc/php.d/wddx.ini, /etc/php.d/xmlreader.ini, /etc/php.d/xmlwriter.ini, /etc/php.d/xsl.ini, /etc/php.d/zip.ini 查看是否启用gd和mbstring库 [root@db-172-16-3-150 drupal]# cat /etc/php.d/gd.ini ; Enable gd extension module extension=gd.so [root@db-172-16-3-150 drupal]# cat /etc/php.d/mbstring.ini ; Enable mbstring extension module extension=mbstring.so
AI 代码解读
现在要重启php-fpm服务来生效新安装的php模块.
service php-fpm restart
AI 代码解读
点击"进行安装", 检测全部通过, 进行下一步, 数据库配置.
注意这里配置的Table prefix不是schema, 而且表的前缀, 防止一个schema下有多个Drupal实例存在的情况造成表名重复.
如果不可能重复的话, 建议字母+下划线的前缀. 或者不要前缀.

开始安装, 提示需要配置bytea output参数 :

配置连接数据库的用户的默认参数,
digoal=# alter role drupal set bytea_output = 'escape'; ALTER ROLE 或者配置drupal728数据库的参数, digoal=# alter database drupal728 set bytea_output = 'escape'; ALTER DATABASE 或者配置PG集群的默认参数. vi $PGDATA/postgresql.conf bytea_output = 'escape'; pg_ctl reload
AI 代码解读
接下来安装过程出错, 违反非空约束如下,

但是表已经安装好了.
drupal728=> \dt List of relations Schema | Name | Type | Owner --------+-----------------------------------+-------+-------- drupal | drupalactions | table | drupal drupal | drupalauthmap | table | drupal drupal | drupalbatch | table | drupal drupal | drupalblock | table | drupal drupal | drupalblock_custom | table | drupal drupal | drupalblock_node_type | table | drupal drupal | drupalblock_role | table | drupal drupal | drupalblocked_ips | table | drupal drupal | drupalcache | table | drupal drupal | drupalcache_block | table | drupal drupal | drupalcache_bootstrap | table | drupal drupal | drupalcache_field | table | drupal drupal | drupalcache_filter | table | drupal drupal | drupalcache_form | table | drupal drupal | drupalcache_image | table | drupal drupal | drupalcache_menu | table | drupal drupal | drupalcache_page | table | drupal drupal | drupalcache_path | table | drupal drupal | drupalcomment | table | drupal drupal | drupaldate_format_locale | table | drupal drupal | drupaldate_format_type | table | drupal drupal | drupaldate_formats | table | drupal drupal | drupalfield_config | table | drupal drupal | drupalfield_config_instance | table | drupal drupal | drupalfield_data_body | table | drupal drupal | drupalfield_data_comment_body | table | drupal drupal | drupalfield_data_field_image | table | drupal drupal | drupalfield_data_field_tags | table | drupal drupal | drupalfield_revision_body | table | drupal drupal | drupalfield_revision_comment_body | table | drupal drupal | drupalfield_revision_field_image | table | drupal drupal | drupalfield_revision_field_tags | table | drupal drupal | drupalfile_managed | table | drupal drupal | drupalfile_usage | table | drupal drupal | drupalfilter | table | drupal drupal | drupalfilter_format | table | drupal drupal | drupalflood | table | drupal drupal | drupalhistory | table | drupal drupal | drupalimage_effects | table | drupal drupal | drupalimage_styles | table | drupal drupal | drupalmenu_custom | table | drupal drupal | drupalmenu_links | table | drupal drupal | drupalmenu_router | table | drupal drupal | drupalnode | table | drupal drupal | drupalnode_access | table | drupal drupal | drupalnode_comment_statistics | table | drupal drupal | drupalnode_revision | table | drupal drupal | drupalnode_type | table | drupal drupal | drupalqueue | table | drupal drupal | drupalrdf_mapping | table | drupal drupal | drupalregistry | table | drupal drupal | drupalregistry_file | table | drupal drupal | drupalrole | table | drupal drupal | drupalrole_permission | table | drupal drupal | drupalsearch_dataset | table | drupal drupal | drupalsearch_index | table | drupal drupal | drupalsearch_node_links | table | drupal drupal | drupalsearch_total | table | drupal drupal | drupalsemaphore | table | drupal drupal | drupalsequences | table | drupal drupal | drupalsessions | table | drupal drupal | drupalshortcut_set | table | drupal drupal | drupalshortcut_set_users | table | drupal drupal | drupalsystem | table | drupal drupal | drupaltaxonomy_index | table | drupal drupal | drupaltaxonomy_term_data | table | drupal drupal | drupaltaxonomy_term_hierarchy | table | drupal drupal | drupaltaxonomy_vocabulary | table | drupal drupal | drupalurl_alias | table | drupal drupal | drupalusers | table | drupal drupal | drupalusers_roles | table | drupal drupal | drupalvariable | table | drupal drupal | drupalwatchdog | table | drupal (73 rows) drupal728=> \df List of functions Schema | Name | Result data type | Argument data types | Type --------+-----------------+------------------+---------------------------+-------- drupal | concat | text | anynonarray, anynonarray | normal drupal | concat | text | anynonarray, text | normal drupal | concat | text | text, anynonarray | normal drupal | concat | text | text, text | normal drupal | greatest | numeric | numeric, numeric | normal drupal | greatest | numeric | numeric, numeric, numeric | normal drupal | rand | double precision | | normal drupal | substring_index | text | text, text, integer | normal (8 rows)
AI 代码解读
非空约束错误, 从postgresql查看日志 :
2014-07-11 21:54:12.543 CST,"drupal","drupal728",21209,"172.16.3.150:62904",53bfec82.52d9,150,"INSERT",2014-07-11 21:54:10 CST,3/290 7,0,ERROR,23502,"null value in column ""rid"" violates not-null constraint","Failing row contains (null, administer blocks, block)." ,,,,,"INSERT INTO drupalrole_permission (rid, permission, module) VALUES (NULL, 'administer blocks', 'block')",,"ExecConstraints, ex ecMain.c:1610",""
AI 代码解读
这个错误可以直接点击the error page, 跳到手工处理配置界面.


完成配置 :


执行完配置后改回权限
cd /opt/site/drupal/ chmod 644 sites/default/settings.php chmod 755 sites/default
AI 代码解读
配置自动开启这些服务.
chkconfig nginx on chkconfig php-fpm on vi /etc/rc.local pg_ctl start
AI 代码解读
[参考]
6. INSTALL.txt