作為一個十多年的Drupal用戶,在接觸百家號/公眾號/簡書后,琢磨各家之長,改造了一下自己的網(wǎng)站,使其具有圖文混排、所見即所得、封面圖、水印、Markdown及語法高亮等功能。
本文講述搭建過程:先用腳本全自動安裝/設置一個基本的Drupal8站點;再手動地稍加配置,使其具有百家號的效果;進一步地配置,達到公眾號和簡書的效果。
廣告:本文高度濃縮。全自動安裝LAMP/LEMP及Drupal,未見有人做到這么完整。再加上百家號/公眾號/簡書效果,以及響應式網(wǎng)頁,其實可以作為幾篇文章??紤]到看官時間寶貴,我就長話短說多合一了。

準備工作
本文在Debian系的Linux(Debian9/8,Ubuntu17)上測試通過。對Redhat系的(比如CentOS),要對apt包(用yum)稍加改造。
先準備一個干凈的系統(tǒng):只需要基本系統(tǒng)、SSH Server。GUI不是必須的。
安裝sudo,并把自己加入sudo組。(Ubuntu上不需要這一步,安裝時創(chuàng)建的賬號默認就可以sudo)
su
apt-get install sudo
adduser your-login sudo
可以在虛擬機上做這個實驗,進行簡單的個人設置后,建一個快照(便于回滾),開始運行腳本。

順便說一句,如果用虛擬機,最好用橋接(Bridge)模式,這樣和主機(Host)在同一個網(wǎng)段。
10分鐘:基本系統(tǒng),全自動腳本
你可以一邊閱讀本章,一邊運行本文最后的腳本。用自己的賬號運行,腳本在需要sudo的時候,會問你密碼。因為sudo會話默認超時是15分鐘,所以最多要輸入兩次密碼(注1)。
默認安裝basic版,我花了大約7分鐘。如果你用國內鏡像,應該會更快。advanced版(主要是支持Markdown)多裝了幾個模塊,那幾個模塊比較花時間,總共大約15分鐘。

下面對腳本做一簡單的說明。
先安裝MySQL, Nginx, PHP。我用輕量級的nginx搭配php-fpm(沒用apache搭配php)。為了適應各系統(tǒng),盡量不指定版本號。Debian9上的MySQL已經(jīng)默認使用MariaDB了,而且安裝時不需要設置root密碼了。這對自動安裝是極好的,sudo mysql 就可以以root登錄MySQL了。Debian8/Ubuntu17上則需要設置一個環(huán)境變量,才能達到同樣的效果。
接下來,安裝composer,PHP的包管理工具;drush,Drupal的命令行工具,讓安裝配置自動化的神器。
軟件裝好后,建一個空的數(shù)據(jù)庫,給Drupal用。順便把相應的賬號密碼寫入自己的~/.my.cnf,便于無密碼使用mysql命令行。
為了全自動,我們直接從nginx網(wǎng)站下載Drupal的配置。怎么從網(wǎng)頁中抓取特定的內容,嚴謹?shù)淖龇ㄟ€是有點小麻煩的,我就簡單粗暴,直接用perl -pe去除所有html tag,得到文本,然后grep -A定位和抓取配置文件內容,最后用perl和sed做一點修改。
最后用drush安裝站點,composer安裝需要的PHP模塊,再用drush創(chuàng)建用戶,安裝/配置模塊、主題。Drupal8還要求把域名加入到信任站點的列表里,否則會有警告。腳本同時也修改了這方面的配置:加入了一個域名,一個服務器的IP地址。
關于權限,養(yǎng)成好習慣,不要全程root:安裝系統(tǒng)軟件,修改系統(tǒng)配置用sudo;安裝Drupal, PHP模塊,用自己的賬號;Drupal的modules, themes, sites/default 目錄最后改為由Web server賬號(www-data)所有,這樣以后可以通過瀏覽器/網(wǎng)頁安裝/缷載Drupal模塊/主題。sites/default如果不改為www-data所有,網(wǎng)頁安裝時會要使用FTP方式,那就麻煩點。
注1:每次運行composer命令(install或require)后,再運行sudo,會要求輸入密碼。這樣,不管sudo會話的超時有多長,這個腳本至少會要兩次sudo的密碼。這是遺憾的地方。
網(wǎng)站管理員和普通用戶的賬號/密碼都在腳本里;安裝腳本成功結束后會提示網(wǎng)站入口地址。
先用管理員登錄。下圖是管理界面之一:系統(tǒng)狀態(tài)。

下圖是用戶權限管理。順便設置權限讓注冊用戶可以創(chuàng)建/修改“文章”(Article)這一類型。順便說一句:如果enable revision,網(wǎng)站立馬就可以變成WiKi類型的站點。

20分鐘:百家號,封面圖
安裝完成后就有了一個所見即所得的編輯器CKEditor,可以實現(xiàn)圖文混排的編輯,和百家號的編輯界面相當。

百家號可以指定3張圖作為封面,而公眾號/簡書是默認使用文中的第一張圖。
為實現(xiàn)百家號的效果,增加一個字段,叫作"Cover”。這個字段可以設置為允許3個值,就是3張圖,和百家號類似。

然后設置這個字段只在摘要頁面(Teaser)顯示,在默認頁面中隱藏(Disabled),這樣,這個封面圖就會只顯示在首頁中,不會顯示在正文中。這樣就實現(xiàn)了百家號的效果。

30分鐘:公眾號,水印
公眾號/訂閱號可以自動給圖片加水印,而百家號和簡書沒這個功能。
在Drupal8中,可以通過模塊 Image effects 來實現(xiàn)水印的效果。
Drupal8用“樣式”(Style)來處理/生成圖片緩存。一種樣式其實就是對原圖的一種/一組處理,最常見的是縮放。Drupal8自帶3種樣式:大、中、?。s略圖)。
我們直接在自帶的 Large 樣式里加入水印這種處理。

水印可以設置:位置,大小,透明度等等。

這樣,對上傳的圖片,顯示的是自動縮?。ㄖ?00x800以內)并帶水印的圖。另外,“水印”本身修改后,也不用重新處理/上傳每一張圖,因為原圖在服務器上,可以重新合成。
40分鐘:簡書,Markdown
簡書支持兩種編輯格式,通常的所見即所得和Markdown。
Drupal里的“格式”也可以做到同樣的事,一種格式(Text format)就是對文本的一組處理/轉換。
新建一種格式,名字叫“Markdown”,其中包括 markdown,語法高亮、自動生成目錄。

使用Markdown,就意味使用純文本編輯器,所以不能用CKEditor上傳圖片了。于是我們回歸原始的Image字段:
- 這個字段是多值的,所以可以上傳任意多張圖片;
- 這個字段不直接顯示在文章中,要在顯示中要設置為”Disabled”(圖在“百家號”那一節(jié));
- 這樣,圖片可以插入在文章的任何位置,和上載的順序無關。
為了幫助在文章里插入圖片的鏈接,使用了Insert模塊。界面如下圖所示:

不足和長處
不足:
- 不支持圖片的剪貼板操作。百家號/公眾號/簡書支持直接粘貼剪貼板內的圖片,自動上載。
- 不支持拖放。簡書是可以支持拖放上載的(百家號看上去也有,但在Chrome里測試未成功)。
- 目前的選圖/插入略感麻煩。簡書的Markdown的同屏編輯/預覽是極好的,在Drupal里用簡單的模塊組合做不出來。
總之,簡書的編輯界面是我見過的最好的。
長處:
- 支持自動生成文章目錄。在文章中插入 “[ toc ]” 就會變成目錄。
- 支持響應式(Responsive )頁面。隨著窗口大小不同,設備不同,界面呈現(xiàn)為不同的布局。這個功能得益于Drupal的主題。Drupal8自帶的主題 Bartik 與時俱進,其實已經(jīng)不錯了。當然,還有不少第三方主題都是響應式的。
- 有大量的第三方模塊/主題。做一個快樂的伸手黨,就能很容易地實現(xiàn)一些功能和效果。
響應式效果簡介:
- 下圖是在手機上顯示的網(wǎng)站首頁——自動變成了單列模式,并隱藏了菜單;
- 在PC上,則顯示為如本文第1圖的雙列模式;如果窗口變窄,也會變?yōu)閱瘟心J剑?/li>
- 在iPad上,旋轉屏幕,也可以看到這種效果的變化。
歡迎訪問我的網(wǎng)站,直接體驗。

下圖是PC上和手機上的文章目錄效果。對于長文章,有目錄還是方便一些。

附:自動安裝腳本
請用具有sudo權限的普通用戶直接運行此腳本,不要以sudo方式運行,也不要用root賬號運行。
腳本在以下系統(tǒng)測試通過:
- Debian 9.0(無GUI);
- Debian 8.8(有GUI);
- Ubuntu 17.04(有GUI)。
腳本可以多次運行。比如安裝好后,再運行腳本,會清除掉數(shù)據(jù)庫重裝;但系統(tǒng)軟件(如果沒有升級版)不會再重裝。
#!/bin/bash
#Setup a Drupal8 site from scratch, including MySQL, Nginx, PHP, Drupal
#Tested on clean Debian9/8, Ubuntu17
#Updated: 6/27/2017, LobLab
set -e
PROFILE=$1
if [ -z "$PROFILE" ]; then
PROFILE=basic
#PROFILE=advanced
fi
DB_NAME=drupal8
DB_USER=drupal8
DB_PASS=JlTpr9wGryiN
SITE_NAME=LobLab
SITE_FQDN=loblab.myvnc.com
SITE_URL=http://$SITE_FQDN
ADMIN_NAME=admin
ADMIN_PASS=P2fOA9b6ctG
ADMIN_MAIL=admin@loblab.com
USER_NAME=demo
USER_PASS=dH9BbntT1Mq
USER_MAIL=demo@loblab.com
DRUPAL_DIR=/var/www/drupal8
DRUSH="drush -r $DRUPAL_DIR -l $SITE_URL -y"
function log_msg() {
echo $(date +'%m/%d %H:%M:%S') - $*
}
function install_system_packages() {
log_msg "Install system packages..."
codename=$(lsb_release -cs)
export DEBIAN_FRONTEND=noninteractive
sudo -E apt-get -y install mysql-server
sudo apt-get -y install mysql-client
sudo apt-get -y install nginx
if [ "$codename" == "jessie" ]; then
sudo apt-get -y install php5-fpm php5-mysql php5-gd
else
sudo apt-get -y install php-fpm php-mysql php-gd php-xml php-mbstring
fi
log_msg "Install system packages... done."
}
function install_php_composer() {
log_msg "Install PHP composer..."
# See https://getcomposer.org/download/
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '669656bab3166a7aff8a7506b8cb2d1c292f042046c5a994c43155c0be6190fa0355160742ab2e1c88d40d5be660b410') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
# See https://getcomposer.org/doc/00-intro.md#globally
sudo mv composer.phar /usr/local/bin/composer
log_msg "Install PHP composer... done."
}
function setup_database() {
log_msg "Setup database..."
sudo mysql -e "CREATE DATABASE IF NOT EXISTS $DB_NAME;"
sudo mysql -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS' WITH GRANT OPTION;"
sudo mysql -e "FLUSH PRIVILEGES;"
echo "[client]" > ~/.my.cnf
echo "user=$DB_USER" >> ~/.my.cnf
echo "password=$DB_PASS" >> ~/.my.cnf
echo "socket=/var/run/mysqld/mysqld.sock" >> ~/.my.cnf
chmod 600 ~/.my.cnf
log_msg "Setup database... done."
}
function setup_nginx_drupal_config() {
log_msg "Donwload nginx config for drupal..."
cfgfile=/etc/nginx/sites-available/drupal8
wget -q -O - https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/ |
perl -pe 's/<.+?>//g' |
grep "server {" -A 102 |
perl -mHTML::Entities -ne 'print HTML::Entities::decode_entities($_);' |
perl -pe "s/server_name .+?;/server_name _;/" |
sed '/location ~ \\..*\/.*\\.php$ {/i \ \ \ \ rewrite ^/core/authorize.php/core/authorize.php(.*)$ /core/authorize.php$1;' |
sudo tee $cfgfile
ps -A | grep php5 && php5=1 || php5=0
if [ $php5 -eq 1 ]; then
sudo perl -pe 's/#(fastcgi_pass.+php5.+fpm.sock;)/$1/' -i $cfgfile
sudo perl -pe 's/(fastcgi_pass.+php7.+fpm.sock;)/#$1/' -i $cfgfile
fi
cd /etc/nginx/sites-enabled
sudo ln -sf $cfgfile drupal8
sudo rm -f default
sudo service nginx restart
log_msg "Donwload nginx config for drupal... done."
}
function install_drush() {
log_msg "Install drush..."
php -r "readfile('http://files.drush.org/drush.phar');" > drush
chmod +x drush
sudo mv drush /usr/local/bin
drush -y init
log_msg "Install drush... done."
}
function install_drupal() {
log_msg "Install drupal..."
#https://www.drupal.org/documentation/install/developers
cd $(dirname $DRUPAL_DIR)
sudo chown -R $MY_ACCOUNT .
drush -y dl drupal --drupal-project-rename=$(basename $DRUPAL_DIR)
cd $DRUPAL_DIR
composer install
if [ "$PROFILE" == "advanced" ]; then
echo "Install PHP module: geshi/geshi..."
composer require geshi/geshi
echo "Install PHP module: michelf/php-markdown..."
composer require michelf/php-markdown
fi
drush -y site-install standard --db-url="mysql://$DB_USER:$DB_PASS@localhost/$DB_NAME" --site-name=$SITE_NAME --account-name="$ADMIN_NAME" --account-pass="$ADMIN_PASS" --account-mail="$ADMIN_MAIL"
host1=$(hostname -I | perl -pe 's/\./\\./g' | perl -pe 's/ //g')
host2=$(echo $SITE_FQDN | perl -pe 's/\./\\./g')
config="\$settings['trusted_host_patterns'] = array(
'^$host1$',
'^$host2$',
);
"
cfgfile=sites/default/settings.php
sudo chmod 644 $cfgfile
echo "$config" >> $cfgfile
sudo chmod 444 $cfgfile
sudo chown -R $WEB_ACCOUNT modules themes sites/default
log_msg "Install drupal... done."
}
function setup_drupal_users() {
log_msg "Create drupal users..."
drush user-create $USER_NAME --password="$USER_PASS" --mail="$USER_MAIL"
log_msg "Create drupal users... done."
}
function setup_drupal_modules() {
log_msg "Download & enable/disable drupal modules..."
sudo chown -R $MY_ACCOUNT modules
$DRUSH en smtp
$DRUSH en image_effects
$DRUSH en insert
$DRUSH en toc_api
$DRUSH en toc_filter
$DRUSH en captcha
$DRUSH en image_captcha
if [ "$PROFILE" == "advanced" ]; then
$DRUSH en geshifilter
$DRUSH en markdown
fi
sudo chown -R $WEB_ACCOUNT modules
log_msg "Download & enable/disable drupal modules... done."
}
function setup_drupal_themes() {
log_msg "Download & enable/disable drupal themes..."
sudo chown -R $MY_ACCOUNT themes
$DRUSH en adminimal_theme
sudo chown -R $WEB_ACCOUNT themes
$DRUSH config-set system.theme default bartik
$DRUSH config-set system.theme admin adminimal_theme
log_msg "Download & enable/disable drupal themes... done."
}
function main() {
install_system_packages
MY_ACCOUNT=$(id -un):$(id -gn)
WEB_ACCOUNT=$(ps -Ao user,group,cmd | grep nginx | grep worker | head -n 1 | awk '{printf "%s:%s\n", $1, $2}')
install_php_composer
install_drush
setup_database
setup_nginx_drupal_config
install_drupal
setup_drupal_users
setup_drupal_modules
setup_drupal_themes
$DRUSH cron
addr=$(hostname -I | sed 's/ //g')
log_msg "Succeeded. Please access http://$addr/"
}
main