记录使用expect遇到的一个坑

记录使用 expect 遇到的一个坑


1. 问题描述

最近写了一个自动化的安装程序,由于要远程操作多台服务器进行安装,所以必然想到了使用 Shell 脚本来自动化。而设计到密码输入的(比如 sudo )则使用 expect 来进行交互,然后被一个小坑浪费了一个下午的时间。

先上代码:

#!/bin/bash
user=${1}
ip=${2}
passwd=${3}


expect -c "
spawn ssh ${user}@${ip} -t 'uname -a'
expect {
    assword: {
        send \"${passwd}\r\"
    }
}
expect eof
"

本质上就是连接到服务器执行命令而已,uname -a 但是脚本竟然报错了:zsh:1: command not found: uname -a(注:真实执行的命令可不是 uname -a 这么简单,这里做示例足够了)。

WTF?

2. 解决过程

想了半天,我一直以为是使用 ssh 登录过去环境变量不对导致的。花了半天时间研究了ssh连接远程主机执行脚本的环境变量问题 这篇文章。虽然没有解决问题,但是文章不错!

苦恼良久,我看到了 send \"${passwd}\r\" 这段代码感到很奇怪。这段 expect 代码是从一个前同事的脚本中扒下来的,整条 expect 命令是由双引号括起来的,字符串参数值替换应该没问题,为什么一定要用转义的双引号呢?

我猜这里可能有什么关键,所以果断把 'uname -a' 改成 \"uname -a\"

结果跑通了!

接下来我又发现 'uname -a' 改成 'uname' 后原来的代码也能跑。

测试了一下午加一个晚上总结出,总结出三种可以跑通的情况:

  1. 不在 expect 命令中而直接以 ssh <user>@<ip> <cmd> 的形式调用。
  2. 'uname -a' 改成 \"uname -a\"
  3. 'uname -a' 改成 'uname'

所以我猜测应该是在使用 expect 时命令体内部在表示 <cmd> 部分出了问题。当命令带 flag 时,单引号没有起到作用,需要使用转义的双引号。

其底层原因我也没时间去探索了,在此 mark 一下吧。

3. 结论

总结来说,expect 命令内部需要用双引号和单引号的还是尽量用转义的双引号吧!

TMUX 自定义配置

QQ20160703-0
TMUX 号称是文本处理的“三大神器”之一,不是没有理由的。最近工作上好多事情都要在服务器上处理,所以用 TMUX 特别频繁。

最近花了点时间自己配置了一下 TMUX,这里权当记录一下吧。

1. 自动加载配置文件

在使用 TMUX 的时候,如果要重新加载配置文件,需要 Ctrl + b 触发,然后输入 : + source-file + ~/.tmux.conf

因为在调试配置的时候需要反复尝试,所以把这个配置做成了快捷键 Ctrl + b + R

bind R source-file ~/.tmux.conf

2. 采用 Vi 模式的快捷键

开启之后在复制模式(copy-mode,Ctrl + b + ?)中可以使用 Vi 模式下的快捷键。

setw -g mode-keys vi

3. 鼠标支持

对于鼠标的支持表现在通过鼠标的点击切换 window、pane 以及通过拖曳更改 pane 的大小。

注意的是 TMUX 版本的不同设置方式也不同。我的 MacBook Pro 使用的是 2.1,而我经常登录的服务器上使用的是 1.6。查看 TMUX 版本的命令是:

tmux -V

如果是 2.1 的话,设置为:

set -g mouse on

如果是 1.6 的话则设置为:

set -g mouse-select-window on
set -g mouse-select-pane on
set -g mouse-resize-pane on

4. 切换 pane 的快捷键

默认的设置中,pane 的切换的快捷键是 Ctrl + b + 方向键,为了更便捷地进行切换,定义了新的快捷键 Alt + 方向键

# 切换为使用 Alt-方向键 切换同一 Window 中的pane
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D

5. 自定义状态栏

TMUX 可以自定义状态栏的颜色和展示信息。首先给出我暂时使用的配置:

# 自动重新编号 window
set -g renumber-windows on

# 设置自动刷新的时间间隔
set -g status-interval 1
# 状态栏左对齐
set -g status-justify left
# 状态栏左侧宽度
set -g status-left-length 20
# 状态栏右侧宽度
set -g status-right-length 50

# 状态栏背景颜色
set -g status-bg '#333333'
# 状态栏前景颜色
set -g status-fg '#ffffff'
# 状态栏左侧显示 session 的名字
set -g status-left '#[bg=#00bb00] [#S] #[default] '
# 状态栏右侧显示时间
#set -g status-right '#[fg=white,bg=#55bb00] [#h] #[fg=white,bg=#009c00] %Y-%m-%d #[fg=white,bg=#007700] %H:%M:%S '
set -g status-right '#[fg=white,bg=#444444] [#h] #[fg=white,bg=#666666] %Y-%m-%d #[fg=white,bg=#888888] %H:%M:%S '

# 当前激活窗口在状态栏的展位格式
setw -g window-status-current-format '#[bg=#ff0000, fg=#ffffff, bold]*[#I] #W*'
# 未激活每个窗口占位的格式
setw -g window-status-format '#[bg=#0000ff, fg=#ffffff] [#I] #W '

有几个配置需要进行说明一下:

5.1 关于时间的配置

上文配置中,我采用了几个时间参数显示在了状态栏的右侧:

参数形式 参数含义
%Y 年:2016
%m 月:07
%d 日:03
%H 小时:02
%M 分钟:19
%S 秒:04

需要注意的是其实这个时间的刷新是有间隔的,我们可以通过设置参数:

set -g status-interval 1

使得状态栏的时间好像每一秒都在变化。

5.2 颜色配置

TMUX 的状态栏中可以按照 #[bg=colourxx,fg=#ffffff] 的形式定义颜色的前景和背景。颜色的类型指定如:blackredgreenyellowbluemagentacyanwhite 。也可以是 colour0 到 colour255。或者形如 #ffffff 的 RGB 格式。同时还可以针对字体进行设置:bright (or bold), dimunderscoreblinkreverse,hidden, or italics

#[default] 可以重置修改后的样式。

5.3 其他配置参数

参数名称 参数含义
#H 完整主机名
#h 不含域名的主机名
#F 窗口的标记
#S session 的名字
#I window 的序号
#W 窗口的名字

此外,我们还可以通过 #(shell_cmd) 的形式运行 shell 命令来增强显示。我们还可以通过 #{VARIABLE} 的形式使用 TMUX 中的各种变量。

  1. 条件变量,例如:#{?session_attached,attached,not attached}。如果 ? 后面的变量存在并且非 0 则返回第一个变量,否则返回第二个。
  2. 变量字符串截取 #{=N:VARIABLE} 的形式获取变量的前 N 个字符, #{=-N:VARIABLE} 获取变量的后 N 个字符。
  3. 如果变量是时间戳类型的,#{t:VARIABLE} 会把时间戳转换为时间字符串。
  4. #{d:VARIABLE} 返回变量的 dirname#{d:VARIABLE} 返回 basename

更多相关配置可见于:FORMATS

6. 我的配置

以下是我的配置,部分配置还是以 2.1 为准。

# 绑定 R 重载配置文件
bind R source-file ~/.tmux.conf

# 采用 vi 模式
setw -g mode-keys vi

# 基本设置
set -g default-terminal "screen-256color"

# 设置序号从1开始
set -g base-index 1
set -g pane-base-index 1

# 关闭状态栏窗口占位的自动命名
setw -g automatic-rename off
set-option -g allow-rename off
setw -g utf8 on
set -g status-utf8 on

# 设定状态栏的位置
set -g status-position bottom

# 状态栏配置 {
    # 自动重新编号 window
    set -g renumber-windows on

    # 设置自动刷新的时间间隔
    set -g status-interval 1
    # 状态栏左对齐
    set -g status-justify left
    # 状态栏左侧宽度
    set -g status-left-length 20
    # 状态栏右侧宽度
    set -g status-right-length 50

    # 状态栏背景颜色
    set -g status-bg '#333333'
    # 状态栏前景颜色
    set -g status-fg '#ffffff'
    # 状态栏左侧显示 session 的名字
    set -g status-left '#[bg=#00bb00] [#S] #[default] '
    # 状态栏右侧显示时间
    #set -g status-right '#[fg=white,bg=#55bb00] [#h] #[fg=white,bg=#009c00] %Y-%m-%d #[fg=white,bg=#007700] %H:%M:%S '
    set -g status-right '#[fg=white,bg=#444444] [#h] #[fg=white,bg=#666666] %Y-%m-%d #[fg=white,bg=#888888] %H:%M:%S '

    # 当前激活窗口在状态栏的展位格式
    setw -g window-status-current-format '#[bg=#ff0000, fg=#ffffff, bold]*[#I] #W*'
    # 未激活每个窗口占位的格式
    setw -g window-status-format '#[bg=#0000ff, fg=#ffffff] [#I] #W '
# }

# tmux 控制相关的配置 {
    # 允许鼠标选取 Window 、Pane 以及 Pane 的大小改变,2.1 时使用如下设置
    set -g mouse on
    # 同上,1.6 时如下设置
    #set -g mouse-select-window on
    #set -g mouse-select-pane on
    #set -g mouse-resize-pane on

    # 切换为使用 Alt-方向键 切换同一 Window 中的pane
    bind -n M-Left select-pane -L
    bind -n M-Right select-pane -R
    bind -n M-Up select-pane -U
    bind -n M-Down select-pane -D
# }

每次学一个这样的高频度软件,都觉得开源世界真尼玛高深莫测,每个软件都有如此复杂的可定制性!还都是免费的!

7. 参考资料

使用 Shell 变量的正确正确姿势

今天发生了在写 Shell脚本的时候发现了一个问题:变量赋值了却取不出来!

当时的代码是这么写的:

V_TS=`date +%Y%m%d`
TABLE_NAME=dwm_xxx_xxx_xxx_metric_day
TEMP_TABLE="es_$TABLE_NAME_$V_TS"

本意是原来的表名加一个前缀 es,加一个后缀日期。结果 TEMP_TABLE 赋值得到的结果是 es_20160303 !!!

仔细一分析,原来在这里把变量名 TABLE_NAME 识别成了 TABLE_NAME_

解决方案也很简单,把

TEMP_TABLE="es_$TABLE_NAME_$V_TS"

改成

TEMP_TABLE="es_${TABLE_NAME}_${V_TS}"

即可,不仅醒目而且消除了歧义!

延伸

扩展一下,上面

V_TS=`date +%Y%m%d`

的写法其实也不太好,用

V_TS=$(date +%Y%m%d)

其实更好。

无独有偶,在计算算数表达式的时候,VAR=$(( 1 + 3 )) 或者 VAR=$[ 1 + 3 ] 就比

VAR=`expr 3 + 1`

来的好。

date 命令小结

最近做的最多的就是把 Hive 查询写到 Shell 脚本中定时调度,常见的有按小时、按天、按周、按月来调度。

所以日期参数的传递就比较重要,这里做一下 date 命令的简单总结。

1. 格式

date [OPTION] [FORMAT]

2. 选项

选项一般是 --date(简写 -d)。

3. 格式

%Y   年,如:2016
%m   月, (01..12)
%d   日,两位
%u   day of week (1..7); 1 is Monday
%V   ISO week number, with Monday as first day of week (01..53)

4. 例子

# 格式化日期
date -d 20160101 +%Y-%m-%d
# 依据某一天进行加减
date -d "-1 days 20160101" +%u
# 文本化的输入
date -d "last sunday" +%Y-%m-%d

Vagrant

1. 简介

Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境。它 使用Oracle的开源VirtualBox虚拟化系统,使用 Chef创建自动化虚拟环境。

我们可以通过 Vagrant 封装一个 Linux 的开发环境,分发给团队成员。成员可以在自己喜欢的桌面系统(Mac/Windows/Linux)上开发程序,代码却能统一在封装好的环境里运行,非常霸气。

2. 安装

2.1 安装 VirtualBox

sudo apt-get install virtualbox-5.0

2.2 安装 Vagrant

下载地址:http://downloads.vagrantup.com/ 根据提示一步步安装。

sudo apt-get install vagrant

2.3 下载官方封装好的基础镜像:

如果你要其他系统的镜像,可以来这里下载

3. 相关操作

3.1 添加镜像

如果下载镜像的存放路径为 ~/path/to/image.box,那么添加 box 的方法为:

vagrant box add <BOX_NAME> ~/path/to/image.box

3.2 初始化开发环境

cd ~/path/to/dev_dir
vagrant init <BOX_NAME> #切换目录
vagrant up #初始化

接着配置环境参数。

vagrant ssh
cd /vagrant

~/path/to/dev_dir 目录对应虚拟机中的 /vagrant

3.3 其他设置

Vagrant 初始化成功后,会在初始化的目录里生成一个 Vagrantfile 的配置文件,可以修改配置文件进行个性化的定制。

Vagrant 默认是使用端口映射方式将虚拟机的端口映射本地从而实现类似 http://localhost:80 这种访问方式。这种方式比较麻烦,新开和修改端口的时候都得编辑。相比较而言,host-only 模式显得方便多了。打开 Vagrantfile,将下面这行的注释去掉(移除#)并保存:

config.vm.network :private_network, ip: "192.168.33.10"

重启虚拟机,这样我们就能用 192.168.33.10 访问这台机器了,你可以把 IP 改成其他地址,只要不产生冲突就行。

3.4 打包

vagrant package

4. 常用命令

vagrant init  # 初始化 
vagrant up  # 启动虚拟机 
vagrant halt  # 关闭虚拟机 
vagrant reload  # 重启虚拟机 
vagrant ssh  # SSH 至虚拟机 
vagrant status  # 查看虚拟机运行状态 
vagrant destroy  # 销毁当前虚拟机

5. 注意事项

使用 Apache/Nginx 时会出现诸如图片修改后但页面刷新仍然是旧文件的情况,是由于静态文件缓存造成的。需要对虚拟机里的 Apache/Nginx 配置文件进行修改:

# Apache 配置添加: 
EnableSendfile off 
# Nginx 配置添加: 
sendfile off;

参考文章

使用 Vagrant 打造跨平台开发环境

SSH 公钥登录与超时断开

最近趁着阿里云针对学生半价买了一个半年的云主机,用下来有两个问题感觉比较蛋疼,一个是每次登录都要输入用户名密码,另一个就是超时自动断开。

公钥登录

ssh 远程连接服务器的验证方法有两种:密码或者公钥。免输密码的解决方法其实很简单,用 expect 命令就可以了。这里介绍一下如何将公钥导入服务器,免除登录时的密码验证。

  1. 前提条件当然是客户端创建了公钥,如果没有请使用 ssh-keygen
  2. 将客户端机器的公钥拷贝至服务器对应用户的家目录下:scp id_rsa.pub user@target_ip:~/
  3. 在服务器上创建 .ssh 目录,并修改权限:mkdir ~/.ssh && chmod 700 ~/.ssh
  4. 创建文件 authorized_keys 并将客户端的公钥写入:cat id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys

超时自动断开

阿里云主机大概一分钟左右没有输入客户端就会死在那里。所以需要设置一下 /etc/ssh/sshd_config 来延长超时时间,配置的内容就两条:

ClientAliveInterval 30
ClientAliveCountMax 200

然后重启一下 sshd 服务,反正我是重启了云主机,然后就行了。

以上。

一个跨平台的离线文档浏览器——Zeal

引言

对于一个程序员来说,查阅编程语言或者框架的手册是家常便饭,但是频繁打开浏览器总是一件很麻烦的事情。

之前在学 Ruby on Rails 时看到了 MacBook 上的 Dash,用起来真方便!可惜也只是 MacBook 上的,我等穷鬼只能羡慕。

小小搜索了一下,在 Github 上发现了一个名为 Zeal 的项目。

Zeal

这个软件的有以下几个特点:

  1. 跨平台。Windows 和 Linux 下都有对应版本。
  2. 支持众多的框架和语言。听过的没听过的都能在这里找到,还可以定制自己的语言手册。
  3. 与集成开发环境和文本编辑器集成。
  4. 支持搜索。

放一张图片:
示例图

更多资料

将WordPress安装或者迁移到万网虚拟机上

万网虚拟机

前一阵子在远景论坛上看到万网的虚拟主机免费,果断申请了一个来使用。使用期间也第一次领教了备案带来的麻烦,好在万网的备案服务还是很好很迅速的,幕布的快递也很给力,就是工信部的审核花了十几天时间。从后台的显示来看,万网的虚拟机可以免费使用两年。这个域名note4code.com也是在万网上购买的,49元/年的价格还算公道。

WordPress的安装

万网的虚拟机使用的操作系统是 CentOS,支持 MySQL和 PHP5.3。WordPress 在该虚拟机上的安装比在 Ubuntu 上安装简单多了(参见上一篇博客在 Ubuntu 上安装 WordPress),不需要安装和设置 Apache2、MySQL 和 PHP,不需要为了修改 URL 而进行的大量操作。安装步骤简单概括就是:

  • 下载 WordPress 源代码。
  • 解压缩文件,创建uploads(wp-content/uploads)文件夹。
  • 复制 wp-config-sample.php,重命名为 wp-config.php 并修改其内容。
/** The name of the database for WordPress */
define('DB_NAME', 'database_name_here');

/** MySQL database username */
define('DB_USER', 'username_here');

/** MySQL database password */
define('DB_PASSWORD', 'password_here');

/** MySQL hostname */
define('DB_HOST', 'localhost');

修改为:

/** The name of the database for WordPress */
define('DB_NAME', 'qdmxxxxxxxxx_db');

/** MySQL database username */
define('DB_USER', 'qdmxxxxxxxxx');

/** MySQL database password */
define('DB_PASSWORD', 'xxxxxxxx');

/** MySQL hostname */
define('DB_HOST', 'qdmxxxxxxxxx.my3w.com');
  • 将所有文件复制到 FTP 服务器的 htdocs 目录下。
  • 登录你的域名(审核已通过的情况下),跟随界面操作。

关于WordPress的迁移

可能不少 WordPress 的用户和我一样,在审核期间就现在本地的 WordPress 上写起了博客,打算在审核通过后再将数据迁移到网上,由于网上相关的经验比较少,我也是花了好几天才摸索出了一套方法。

1.导出上传的图片

在写博客的时候不可避免会用到一些图片,这些图片应该都存在我们建立的 uploads 文件夹里,在向 FTP 服务器复制文件的时候记得将原来的 uploads 文件夹合并到 FTP 上去。

2.导出数据库

我们的文章都存在数据库中,所以 WordPress 的迁移本质上是数据库的迁移,我们首先导出数据库:

mysqldump -u wpuser -p wordpress > wordpress.sql

输入该用户的密码后我们得到一个名为 wordpress.sql 的文件,打开文件删除所有类似 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 的语句和注释,仅保留创建表和插入数据的语句。然后使用 Vim(没错,我支持 Vim)的全局替换字符串功能,将 localhost/wordpress 替换为你的域名。

3.导入数据库

进入虚拟主机数据库的管理界面,导入我们修改好的脚本即可。至此大功告成!

注意:在导入数据前最好将本地WordPress使用的插件在虚拟主机上提前装好,避免数据出现错误或者不一致的情况!

在Ubuntu上安装WordPress(附脚本)

WordPress简介

WordPress是一种使用PHP和MySQL开发的博客平台,其实对个人来说也可以当做一个像印象笔记一样的个人知识、内容管理平台。同时各种第三方的插件、主题也让WordPress具备了独特的个性化选择。

手动安装WordPress

安装WordPress相对来说是一个比较简单的过程,只要按照以下步骤执行,一般都可以顺利安装。

1.安装依赖的软件包

第一步要在Ubuntu上安装WordPress所依赖的MySQL、Apache2、PHP等软件包,具体安装方法如下:

sudo apt-get install apache2
sudo apt-get install libapache2-mod-php5 php5
sudo apt-get install mysql-server-5.0  mysql-common mysql-admin
sudo apt-get install php5-mysql

2.配置MySQL

在上一步中安装完MySQL之后记住MySQL的root用户的密码,在这一步中将会使用。使用如下命令来进入MySQL数据库:

mysql -u root -p

然后输入密码进入MySQL。接着我们创建WordPress所使用的数据库:

create database wordpress;

接着为WordPress创建用户并将数据库wordpress的所有权限赋予这个用户:

create user wpuser@localhost identified by 'wppasswd';
grant all privileges on wordpress.* to wpuser@localhost;
flush privileges;

3.下载并安装WordPress

WordPress的安装文件既可以访问中文官方网站进行下载,也可以使用wget命令下载:

wget -c http://wordpress.org/latest.tar.gz

下载完成后解压文件,复制 wp-config-sample.php 文件并重命名为 wp-config.php,并将相关参数进行替换,将

/** The name of the database for WordPress */
define('DB_NAME', 'database_name_here');

/** MySQL database username */
define('DB_USER', 'username_here');

/** MySQL database password */
define('DB_PASSWORD', 'password_here');

/** MySQL hostname */
define('DB_HOST', 'localhost');

修改为:

/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');

/** MySQL database username */
define('DB_USER', 'wpuser');

/** MySQL database password */
define('DB_PASSWORD', 'wppasswd');

/** MySQL hostname */
define('DB_HOST', 'localhost');

其中’DB_HOST’因为MySQL就在本地所以就不用修改localhost,如果数据库位于其他服务器那么就应该填写相应域名或者IP地址。

4.拷贝WordPress解压文件至Apache2服务器目录下

我们要将解压出来的wordpress文件夹拷贝至/var/www/html/下面,为其创建uploads文件夹(保存上传的图片)并修改文件的拥有者为www-data。

sudo rsync -avP ./wordpress /var/www/html/
sudo mkdir /var/www/html/wordpress/wp-content/uploads
sudo chown -R www-data:www-data /var/www/html/wordpress/*

5.安装MySQL扩展

如果遇到“ Your PHP installation appears to be missing the MySQL extension which is required by WordPress ”的情况,一般在 /etc/php5/apache2/php.ini 中将“ extension=/path/to/extension/mysql.so ”改为“ extension=mysql.so ”就可以了。

6.修改apache2的配置文件来允许URL的重写

本步骤的目的是为了允许WordPress能够自定义固定链接的格式。在/etc/apache2/sites-available/000-default.conf中添加下文星号包括的部分:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    *ServerName 127.0.0.1*
    *<Directory /var/www/html/>*
        *AllowOverride All*
    *</Directory>*
    . . .

然后使用如下命令来允许URL的重写以及Apache2的重启:

sudo a2enmod rewrite
sudo service apache2 restart

最后创建 .htaccess 文件并修改其权限与所有者:

touch /var/www/html/wordpress/.htaccess
sudo chown :www-data /var/www/html/wordpress/.htaccess
chmod 664 /var/www/html/wordpress/.htaccess

7.著名的5分钟安装

打开浏览器登录 http://localhost/wordpress 按照图形界面的提示操作即可。

Shell脚本

以下的脚本本人亲测,使用了expect命令来简化设置过程,并添加了几个步骤来修正可能出现的问题.

#!/bin/sh

if [ $# -ne 4 ]; then
    echo "Usage: sudo sh $0 db_name user_name user_passwd mysql_root_passwd"
    exit 1
fi

db_name=$1
user_name=$2
user_passwd=$3
mysql_root_passwd=$4

install_dependency(){
    #1. install the dependency of wordpress
    sudo apt-get install apache2
    sudo apt-get install libapache2-mod-php5 php5
    sudo apt-get install mysql-server mysql-common
    sudo apt-get install php5-mysql
}

config_mysql(){
    #2. configure mysql
sudo apt-get install expect
expect << EOF
set timeout 100
spawn mysql -u root -p
expect {
    "Enter password:" {send "$mysql_root_passwd\r"}
}
expect "mysql>"
send "create database $db_name;\r"
expect "mysql>"
send "create user $user_name@localhost identified by '$user_passwd';\r"
expect "mysql>"
send "grant all privileges on $db_name.* to $user_name@localhost;\r"
expect "mysql>"
send "flush privileges;\r"
expect "mysql>"
send "exit\r"
EOF
}

install_wordpress(){
    #3. install wordpress
    #3.1 download the wordpress
    wget -c http://wordpress.org/latest.tar.gz
    #3.2 extract the files to rebuild wordpress
    tar xvfz latest.tar.gz
    sudo rm -f latest.tar.gz
    #3.3 install some packages to allow you to work with images, install plugins and update portions of your site using ssh.
    sudo apt-get install php5-gd libssh2-php
}

config_wordpress(){
    #4. configure wordpress
    sed "s/database_name_here/$db_name/" ./wordpress/wp-config-sample.php | sed "s/username_here/$user_name/" | sed "s/password_here/$user_passwd/" >> ./wordpress/wp-config.php
}

copy_files(){
    #5. copy files to the document root
    sudo rsync -avP ./wordpress /var/www/html/
    sudo rm -rf ./wordpress
    sudo mkdir /var/www/html/wordpress/wp-content/uploads
    sudo chown -R www-data:www-data /var/www/html/wordpress/*
}

install_mysql_extension(){
    #6. when the problem "Your PHP installation appears to be missing the MySQL extension which is required by WordPress" occurs, you need this.
    sudo sed -i "s/extension=\/path\/to\/extension\/msql.so/extension=mysql.so/" /etc/php5/apache2/php.ini
}

modify_apache_to_allow_url_rewrites(){
    date_time=$(date +%y%m%d%H%M)
    sudo cp /etc/apache2/sites-available/000-default.conf "/etc/apache2/sites-available/000-default.conf.$date_time.bak"
    sudo sed -i "/<\/VirtualHost>/i \        ServerName 127.0.0.1\n        <Directory \/var\/www\/html\/wordpress\/>\n            AllowOverride All\n        <\/Directory>" /etc/apache2/sites-available/000-default.conf
    sudo a2enmod rewrite
    sudo echo 'ServerName localhost' >> /etc/apache2/apache2.conf
    sudo service apache2 restart
}

create_htaccess_file(){
    touch /var/www/html/wordpress/.htaccess
    sudo chown :www-data /var/www/html/wordpress/.htaccess
    chmod 664 /var/www/html/wordpress/.htaccess
}

#install_dependency
config_mysql
install_wordpress
config_wordpress
copy_files
install_mysql_extension
modify_apache_to_allow_url_rewrites
create_htaccess_file

exit 0

参考资料

Markdown基本语法

认识 Markdown 是从使用Github开始的,一直很好奇那个.md 文件到底是干什么的。直到在某次在伯乐在线看到了到了关于Markdown的介绍才有所了解。之前虽然在使用 MediaWiki的时候略微了解了一下语法但是使用时间很短早就忘掉了。直到最近开始使用 IPython Notebook 了,那就好好学习一下优雅的 Markdown 吧!

吐槽一下,博客园的 Markdown 真是渣,显示效果好多不对。

  • 标题与标题之间间距、标题与正文之间的间距
  • 有序列表的嵌套
  • 为什么***就显示不了分割线呢?

1.段落

  1. 单个回车视为空格,多个回车才能分段。
  2. 行尾加两个空格实现段内换行。

2.标题

# 一级标题

## 二级标题

### 三级标题

……

3.区块引用

一级引用在段落前加一个 >,如果二级引用则使用 >>。

> + 这是一个引用的第一行。
这是第二行。
> > – 这是一个嵌套引用的第一行。
嵌套引用第二行。
>
> + 外层引用的第三行

效果:

  • 这是一个引用的第一行。
    这是第二行。

    • 这是一个嵌套引用的第一行。
      嵌套引用第二行。
  • 外层引用的第三行

4.列表

列表分为有序列表和无序列表。
无序列表的定义形式:

* 无序列表中的一项,注意星号以后有空格
  * 无序列表的子项,要以一个制表符或者4个空格缩进
* 无序列表中的第二项

效果:

  • 无序列表中的一项,注意星号以后有空格
    • 无序列表的子项,要以一个制表符或者4个空格缩进
  • 无序列表中的第二项

有序列表的定义形式

1. 有序列表有编号,数字后面紧跟一个空格
 1. 子项起始处保持一个空格缩进
 2. * 或者英文 . 之后保留一个空格
2. 有序列表中的第二项

效果:

  1. 有序列表有编号,数字后面紧跟一个空格
    1. 子项起始处保持一个空格缩进
    2. * 或者英文 . 之后保留一个空格
  2. 有序列表中的第二项

5.代码区块

如果想要插入代码有两种方式。一个是用反引号 ` 包起来,一种是用制表符或至少四个空格缩进。

  void Hello(){ System.out.println(“Hello World!”)}

效果:

void Hello(){ System.out.println("Hello World!")}

6.分割线

3个或3个以上的 ***


7.链接

地址链接

[需要显示的文字](链接地址),例:

[Dr. Lightman](http://www.cnblogs.com/NO-30/)
效果: Dr. Lightman


图片链接

![图片的替代文字](URL),例:

![测试图片](http://pic.cnitblog.com/avatar/504460/20130316182932.png)
测试图片


参考形式

[Dr. Ligthman][1]
![Dr. Ligthman Logo][2]

[1]:http://www.cnblogs.com/NO-30/
[2]:http://pic.cnitblog.com/avatar/504460/20130316182932.png

效果:

Dr. Ligthman
Dr. Ligthman Logo

8.强调

  1. *斜体* 的效果为 斜体
  2. **粗体** 的效果是 粗体

9.反斜杠

反斜杠用来作为转义字符,比如放在 * 前面取消斜体的转义等。

尾声

最后推荐一下我使用过的几个在线 Markdown 编辑器:

个人觉得最赞的还是马克飞象。这三个在线编辑器都提供了丰富的文本编辑功能,但是马克飞象可以连接印象笔记,方便内容的管理和组织。马克飞象还支持在线编辑文档的导出,支持 Markdown、HTML、PDF 三种格式。

你给别人传文件最先想到什么格式?当然是PDF!打印到纸上是真正的所见即所得,还能防止文档被修改。虽然 PDF 导出还需要借助 Chrome 的打印功能,但是这个功能还是很赞!