May 2014 Blog Posts

Linux下如何批量建立文件软连接(极简版)

MitchellChu 2014-05-21 Unix & Linux

上一篇里面是通过创建了Shell脚本文件的方式来批量创建文件的软链接,由于Shell脚本处在(Linux)菜鸟阶段,那个脚本文件的编写完全是现学现卖——Shell语法都没看完,这我会告诉你吗,告诉你会信吗?所以引出的一个问题是:此脚本虽然能正确处理任务但肯定还有很多地方的处理值得商榷。为此也花了一些时间思考了一下如何不要使用shell脚本文件来处理批量建立软链接的问题,后来确有一些思路,在上篇成文之时已经有了一些方法,所以当时卖了一个关子。

要一行脚本代码来建立批量的文件软链,Mitchell的思路主要在通道的使用上,我希望能够这样:

## 代码是示意,并不能正常运行
ls /tmp/*.log | ln -s .....

但在下这个通道我并没有知道合适的传递参数的方法。只能告一个段落。换种思路,就是将文件列表用for循环来处理。于是,有了下面的脚本:

## 获取目录下要软链接的文件,让后用for遍历文件来创建软链接。
FILES=`ls *.log`;for FILE in $FILES;do ln -s '/tmp/'$FILE '/tmp/lnk_'$FILE;done

但这个只能放到目标目录下,这是/tmp目录,然后运行,因为FILE遍历出来不能含有路径。为了改善这个缺点,做了改进:

## 使用basename来将路径过滤掉,只取文件名称
FILES=`ls /tmp/*.log`;for FILE in $FILES;do ln -s $FILE '/tmp/lnk_'`basename $FILE`;done

后来发现,此处还可以继续改进,在Linux下你可以这样:

## create all files' soft link in '/tmp/' which subfix is log, and all link files' save to /tmp/ with prefix 'lnk_'
for FILE in /tmp/*.log;do ln -s $FILE '/tmp/lnk_'`basename $FILE`;done

 这样就可以在任意位置下运行这个代码,只要修改目标路径和存放链接的路径即可。

 很酷吧,这样就可以实现上一篇的那么东西。来吧,看看更酷的,回到前面的通道,我们虽然没有办法直接将数据直接传递给ln,但是我们可以这样

## Create a batch of soft-link files with pipeline
ls /tmp/*.log | xargs -L 1 -i sh -c "ln -s {} '/tmp/lnk_'\$(basename {})"

 哇噢~ 原来通道也可以这么来做,当然,Mitchell对Linux的命令还不是很了解,但我相信肯定可以在这个基础上,再精简出更酷的代码的。

恩,看了上面两种方法,是不是瞬间觉得好有难度——恭喜,Same as me。搞这个软链接,需要这么消耗脑细胞吗。记得原来的cp好像有个参数是创建连接的,于是,翻看了cp的命令帮助,加之网络搜索大神附身,不多久,出来了cp版:

## create a batch of soft-link files with cp command.
## this command can not create soft-link file with prefix or subfix
## so it can not create soft-link file at same directory.
cp -rs /tmp/*.log /tmp/lnk/

这个版本太简单了吧,和前面的比,这个命令无法在同目录下创建软链接,但应该没有人有这么奇怪的需求——除了我测试之外。

写到这里,震惊了么,至少我是这样的,从开始写文件,到这里,这个工作量差距不是一点两点。如果你还没有震惊,那么你看看这个:

## create a batch of soft-link files with ln command
## similar to cp -rs
ln -s /tmp/*.log /tmp/lnk/

这... 看到可以这样用的时候,我无语了,原来ln自己就可以做批量创建啊!内心有无数只,无数只,无数只[哔哔哔]奔过啊。

到这里,终于被我自己的努力证的了一个完美的循环,有句话果然毁人不倦:从哪里来,到哪里去!

 

Linux下如何用Shell脚本批量创建文件软链接

MitchellChu 2014-05-21 Unix & Linux
这篇是个人Shell脚本的初作,功能是批量创建文件的软链接。文中值得商榷之处肯定非常多,欢迎大家指点。
—— MitchellChu

最近在,具体说是CentOS (v 6)下,因为自定义安装的软件太多,而自定义安装之后,由于系统的PATH中没有安装软件的路径,每次都需要将安装后的软件可执行文件在PATH里面有的bin目录下创建软链接,以此来达到直接可以调用的目的。一个文件两个文件也许还好,可有的软件需要弄出个一大堆的文件要软链接,在Shell下一个一个命令的敲,确实不是一个事情。也正因此,才有了此篇博文——Linux下用Shell脚本来批量创建文件的软链接。

要批量创建文件的软链接,自然要想想下我的脚本应该是能够提供什么样功能的(需求):由于初期没有什么特别要求,只要批量创建软链接即可,但创建软链接是使用ln -s target_file link_file的格式来的,所以,1. shell脚本要可以接收到这两个关键因素!2.如果仅仅是接受这两个参数,就没有批量创建软链接一说了,因此,还应该有个文件过滤器,能够将需要批量创建的文件筛选出来。

需求明确成:shell脚本能够过滤出需要创建软链接的文件,并通过ln命令在目标目录中

根据这个需求,捣鼓了一下,弄出了BatchLinkFilesCreater.sh:

#!/bin/sh
########################
## ARGUMENTS:
## TARGET_DIR: the directory where the link file to link.
## FILES_FILTER: this is the arguments of the ls command.
## LINK_DIR: where is the link file to save.
########################
function usagehelp()
{
        echo -e "Usage:batchCreateLink.sh -t TARGET_DIR -f FILES-FILTER -l LINK-DIR\n\n
                TARGET_DIR: the directory where the link file to link\n\n
                FILES_FILTER: arguments of ls command, to filter the list files.\n\n
                LINK_DIR: where is the link file to save.\n\n\n
                sample:./batchCreateLink.sh -t \"/usr/local/bin/\" -f \"*\" -l \"/tmp/\"\n
                any problems please contact MitchellChu, http://blog.useasp.net/"
}

if [ $# != 6 ]
then
        usagehelp
        exit 1
fi

echo "======================================="
echo "Multiple link files Creater"
echo -e "version:0.0.0.1\n"
echo "ARGUMENTS:"

while getopts "t:f:l:" arg
do
        case $arg in
                t)
                        echo "->TARGET_DIR:$OPTARG"
                        TARGET_DIR=`dirname $OPTARG"/*"`;;
                f)
                        echo "->FILES_FILTER:$OPTARG"
                        FILES_FILTER=$OPTARG
                        ;;
                l)
                        echo "->LINK_DIR:$OPTARG"
                        LINK_DIR=`dirname $OPTARG"/*"`;;
                ?)
                        usagehelp
                        exit 1;;
        esac
done

echo "======================================="

cd $TARGET_DIR
if [ `pwd` != $TARGET_DIR ]
then
        echo "$TARGET_DIR is not exist."
        exit 1
fi

cd $LINK_DIR
if [ `pwd` != $LINK_DIR ]
then
        echo "LINK DIR:$LINK_DIR is not exist."
        exit 1
fi

cd $TARGET_DIR
echo -e "\n"
for FILENAME in $FILES_FILTER
do
        if [ $FILENAME ]
        then
                echo -e $LINK_DIR"/"$FILENAME" ----> "$TARGET_DIR"/"$FILENAME
                ln -s $TARGET_DIR"/"$FILENAME $LINK_DIR"/"$FILENAME
        fi
done
echo -e "\n\n[DONE]"

 这个脚本文件做的事情很简单:根据用户输入的目标文件夹,连接存放的文件夹和文件过滤参数,自动完成在目标文件夹中根据文件过滤规则过滤出需要创建软链接的文件,然后在需要软链接的存放文件夹内创建每一个文件的软链接,链接文件的目标自然是对应的目标文件夹内的文件。

为了能够更健壮点,添加了一些校验脚本,上面的脚本可保存到任意目录下,同时赋予可执行权限:

chmod +x BatchLinkFilesCreater.sh
## 如果仅仅是自己使用,则可以
chmod u+x BatchLinkFilesCreater.sh

在有执行权限后,你就可以根据你的需要调用这个shell脚本来批量创建了。

BatchLinkFilesCreater.sh脚本的参数说明:
-t TARGET_DIR,目标文件夹,就是要创建软连接的目标文件所在文件夹
-f FILES_FILTER,此参数是-t指定的文件夹内的文件过滤参数,根据此参数指定的过滤规则筛选出要创建软链接的文件。
-l LINK_DIR,被创建的软链接存放的文件夹。

文件功能:在LINK_DIR内创建TARGET_DIR内用FILES_FILTER筛选出来的文件的软连接。

如:

## 在/tmp目录下创建/tmp下所有以[.log]结尾的文件的软连接。
## 必要的时候你可能需要sudo来获得权限
./BatchLinkFilesCreater.sh -t "/tmp/" -f "*.log" -l "/tmp/"

 当然,这是测试,要删除测试文件,请使用find命令:

## 删除上面代码创建在/tmp目录下的以.log结尾的软链接.
find /tmp/ -maxdepth 1 -type l -name "*.log" -exec rm -f {} \;

OK,目标任务基本完成,有了这个shell脚本,批量创建软链接是完全没有问题的。如果你愿意,可以将脚本改成任何其他需要批量处理的脚本代码——TIPs:仅需要很少的修改。包括但不限于:

  1. 批量文件备份
  2. 批量文件改名

试试,看还能怎么用?我也在思考中ing...

哼,哼,嗯哼……那个,其实要实现批量建立文件的软链接并不需要这么复杂的Shell脚本处理哦,一行命令就可以,真的,一行命令!怎么做?卖个关子,请参看后继博文吧~~

SSH客户端(如PuTTY)ssh远程登录Linux非常慢的解决方法

MitchellChu 2014-05-19 Unix & Linux

每次PuTTY使用SSH登录到远程的进行管理的时候,远程登录的过程都非常慢——输入完用户名之后,非要等到30秒左右才会出来输入密码的提示。在实际处理问题的时候,特别需要快速响应的时候,这种状况着实让人难以忍受。

但后来具体测试了一下,发现这又并非是每种系统的通病,出现问题的机器主要集中的CentOS上,同样的Debian系统,在远程连接的过程就是健步如飞,丝毫没有卡顿犹豫的感觉。这难道是CentOS的问题?出于好奇,查看了下两个系统在SSH时的差别。

CentOS:

ssh -v ssh_test@192.168.128.137

的时候显示的信息如下:

OpenSSH_6.0p1 Debian-4, OpenSSL 1.0.1e 11 Feb 2013
...Some sensitive information...
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3
debug1: match: OpenSSH_5.3 pat OpenSSH_5*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.0p1 Debian-4
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
...Some sensitive information...
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Next authentication method: gssapi-keyex
debug1: No valid Key exchange context
debug1: Next authentication method: gssapi-with-mic
debug1: Unspecified GSS failure.  Minor code may provide more information
Cannot determine realm for numeric host address

debug1: Unspecified GSS failure.  Minor code may provide more information
Cannot determine realm for numeric host address

debug1: Unspecified GSS failure.  Minor code may provide more information


debug1: Unspecified GSS failure.  Minor code may provide more information
Cannot determine realm for numeric host address

debug1: Next authentication method: publickey
debug1: Trying private key: /home/mitchellchu/.ssh/id_rsa
debug1: Trying private key: /home/mitchellchu/.ssh/id_dsa
debug1: Trying private key: /home/mitchellchu/.ssh/id_ecdsa
debug1: Next authentication method: password

而Debian使用同样的命令测试的结果为:

OpenSSH_6.0p1 Debian-4, OpenSSL 1.0.1e 11 Feb 2013
...Some sensitive information...
debug1: Remote protocol version 2.0, remote software version OpenSSH_6.0p1 Debian-4
debug1: match: OpenSSH_6.0p1 Debian-4 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.0p1 Debian-4
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
...Some sensitive information...
debug1: ssh_ecdsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Trying private key: /home/mitchellchu/.ssh/id_rsa
debug1: Trying private key: /home/mitchellchu/.ssh/id_dsa
debug1: Trying private key: /home/mitchellchu/.ssh/id_ecdsa
debug1: Next authentication method: password

从上面可以看到,在CentOS中,系统使用了publickey,gssapi-keyex,gssapi-with-mic,和password来进行认证(上面颜色标记行,23行),而Debian此时则使用了Publickey和password两种。在连接CentOS的时候,在23行处花费了相当多的时间。我们在那里开始往下看,就能非常清楚的看到下面的信息:

#下面使用的是GSSAPI-KEYEX来进行验证
debug1: Next authentication method: gssapi-keyex
#但是报错:没有可用的Key来交换信息
debug1: No valid Key exchange context
#系统接着又使用下一个验证方法:GSSAPI-WITH-MIC
debug1: Next authentication method: gssapi-with-mic
#但遗憾的是,GSSAPI-WITH-MIC方法也失败。
#原因:不能确定数字主机地址的域
debug1: Unspecified GSS failure.  Minor code may provide more information
Cannot determine realm for numeric host address

debug1: Unspecified GSS failure.  Minor code may provide more information
Cannot determine realm for numeric host address

debug1: Unspecified GSS failure.  Minor code may provide more information


debug1: Unspecified GSS failure.  Minor code may provide more information
Cannot determine realm for numeric host address
# 在尝试几次后,SSH认证终于放弃了这种验证。进入下一个验证:Publickey
debug1: Next authentication method: publickey

 从错误可以看出应该是和主机域相关的问题——应该是无法确认IP对应的域,因此会出现这个问题。GSSAPI1主要是基于Kerberos的,因此要解决这个问题也就变得要系统配置有Kerberos,这对于没有Kerberos的筒子们来说,配置个Kerberos就为了解决个登录延时问题,似乎不是个明智的决定——特别是在生产环境中!最小化满足需求才是王道。

除了这个方法还有其他方法么?这个自然是有的,Debian其实就已经提供给我们一个解决方案了——使用ssh的时候禁用GSSAPI验证。当然,还有一个问题不得不注意,如果你的机器上启用了UseDNS2的话,需要一并关闭,具体可参见最后的说明。

下面先放出处理GSSAPI的方法。

禁用GSSAPI认证有两个方式:客户端和服务端

1. 客户端禁用比较简单,影响的只有单个客户端用户,可以用下面的方法实现:

ssh -o GSSAPIAuthentication=no your-server-username@serverIP

 用上面的方法登录远程,即可实现禁用GSSAPIAuthentication。如果你嫌麻烦,直接配置你ssh客户端的文件 /etc/ssh/ssh_config来达到永久解决这个问题:

vi /etc/ssh/ssh_config
### 找到ssh_config文件里面的GSSAPIAuthentication yes这行
### 修改为GSSAPIAuthentication no
### 保存ssh_config文件并退出

 这个修改方法是将所有这个机器上的用户都影响到了,如果你影响面不要那么的广泛,只要在指定的用户上实施禁用GSSAPIAuthentication的话,那么你可以在该用户的目录下,找到.ssh目录,在其下面添加config文件,并在文件内添加上面这句,如果没有这个文件,你也可以直接这么做:

cat >>~/.ssh/config<<EOF
GSSAPIAuthentication no
EOF

使用cat,直接将输入导出到文件中,这时候,你在使用ssh连接远程的目标主机时,就不会再使用了。

上面这些文件是在客户端,不是服务端的。也就是说,要修改这个文件,你的客户端也要是Linux才行。如果你是在Windows下使用这样的客户端工具,就不使用上面这个方法了,PuTTY下可以尝试在连接之前进行设置:

### PuTTY下设置不使用GSSAPIAuthentication
PuTTY Configuration -> Connection -> SSH -> Auth -> GSSAPI -> (取消勾选)Attempt GSSAPI authentication(SSH-2 only)

 如果没有关闭PuTTY的GSSAPIAuthentication,你可以在连接的窗口右键(或:Ctrl + 右键)查看日志,可以发现PuTTY会自动尝试GSSAPI连接的日志:

2014-05-18 23:46:54  Using SSPI from SECUR32.DLL
2014-05-18 23:46:54 Attempting GSSAPI authentication
2014-05-18 23:46:54 GSSAPI authentication request refused

恩,上面基本上将客户端禁止GSSAPIAuthentication的方法罗列了一下。

注意:上面这些方法是在比较通用的,如果你已经配置了Kerberos的情况下,那么你也可以尝试下下面这个客户端解决这个问题的方法:添加远程主机的主机名到你本机的host文件中(Linux是/etc/hosts,Windows是系统盘:\Windows\System32\drivers\etc\hosts):

### Linux和Windows下都可以添加下面这行
### 注意:下面这样的IP-Addr要替换成你的远程机器的IP地址,HostName,自然是主机名
IP-Addr HostName
### 添加完毕之后,保存退出。

如果你没有配置Kerberos的话,仅配置这个hosts文件一样是不能解决问题的,在使用ssh登录的时候,你可以看到报错日志会类似下面这样:

debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mi
debug1: Next authentication method: gssapi-keyex
debug1: No valid Key exchange context
debug1: Next authentication method: gssapi-with-mic
debug1: Unspecified GSS failure.  Minor code may provide more information
Credentials cache file '/tmp/krb5cc_0' not found

debug1: Unspecified GSS failure.  Minor code may provide more information
Credentials cache file '/tmp/krb5cc_0' not found

debug1: Unspecified GSS failure.  Minor code may provide more information


debug1: Unspecified GSS failure.  Minor code may provide more information
Credentials cache file '/tmp/krb5cc_0' not found

debug1: Next authentication method: publickey

 这个错误我在刚开始的时候也犯了的,需要注意。

2.服务端禁用GSSAPIAuthentication。

直接到/etc/ssh/sshd_config里面,将GSSAPIAuthentication yes改为no即可了,同时也请注意,你可能也需要将UseDNS2这个也修改成UseDNS no(这个要注意,每个系统的默认值不同,此处以CentOS 6为例):

sudo vi /etc/ssh/sshd_config
###普通用户权限不够,需要root权限
###找到GSSAPIAuthentication yes,修改为
### GSSAPIAuthentication no
### 注意,这里你也需要将UseDNS修改为no,CentOS默认是yes,即使这行已被注释,你也需要加上
### UseDNS no
### 有看到人说UseDNS yes不需要修改为UseDNS no,Mitchell测试下来是需要的。
###保存文件,退出

 当禁用之后,我们需要重启SSH服务来保证新的配置文件被正确应用:

service sshd restart

这个时候,再次使用SSH登录这个主机时,是不是感觉飞快了?

呼~ 终于完成了这边长文,要一边捣腾一边弄出这些个文字,还是真是有点困难。不过,这样也就将问题捣腾的差不多了,希望看文章的你能够看的明白,欢迎讨论。 

 

说明:

1. GSSAPI:Generic Security Services Application Program Interface,GSSAPI本身是一套API,由IETF标准化。其最主要也是著名的实现是基于Kerberos的。一般说到GSSAPI都暗指Kerberos实现。

2. UseDNS:是OpenSSH服务器上的一个DNS查找选项,而且默认还是打开的,在打开的状态下,每当客户端尝试连接OpenSSH服务器的时候,服务端就自动根据用户客户端的IP进行DNS PTR反向查询(IP反向解析才会有记录),查询出IP对应的Hostname,之后在根据客户端的Hostname进行DNS正向A记录查询。通过这个查询,验证IP是否和连接的客户端IP一致。但绝大部分我们的机器是动态获取IP的,也就是说,这个选项对于这种情况根本就没用——即使是普通静态IP服务器,只要没有做IP反向解析,也难以适用。如果你符合这些情况,建议关闭UseDNS以提高SSH远程登录时候的认证速度。

Linux下Putty链接后Emacs黑底蓝字处理

MitchellChu 2014-05-14 其他技术 Unix & Linux

在CentOS 6下装了一个Emacs24.3,在宿主终端上显示Emacs的字体还是非常不错的,可是用Putty一连接,的字体就抽风,里面的链接变成了黑底蓝字——作死的节奏啊这是!在屏幕上只能看到蓝色的一小团,贴近了看才能看清楚字的内容。后来,一查才发现,原来是终端连接上没有开启xterm-256色。

查看设置:

tput colors
## 如果是显示8,恭喜,xterm终端默认还是8色
echo $TERM
## 查看终端类型,CentOS下默认好像是xterm

 如果你也是上面显示的这个数值,那说明同样没有开启对终端的256色的支持。

开启256色的支持要做2件事情:

1. Putty客户端工具里面要开启对Xterm-256colors的支持

Putty设置:
Putty->Change Settings...->Window->Colors->(勾选)Allow terminal to use xterm 256-colors mode->Apply

2. CentOS()上开启Xterm-256colors

 开启Xterm-256color有两种方式,其一是修改连接用户的.bashrc文件;其二是修改.Xresources文件。如果是使用CentOS的命令行模式(没有安装XWindow)的话,.Xresources文件可能不存在,此时可以用第一种方式实现。

修改~/.bashrc

## 务必注意,修改的是使用PuTTY连接到Linux的用户目录下的.bashrc
vi ~/.bashrc
## 打开用户的.bashrc文件
## 在末尾附加下面代码
if [ "$TERM" == "xterm" ]; then
        export TERM=xterm-256color
fi

## 保存~/.bashrc文件

修改~/.Xresources:

##在~/.Xresources文件中添加下面这句
xterm*termName:xterm-256color
##保存~/.Xresources文件

修改完成后,记得重新登录下,以便让修改后的配置生效。生效后,再次输入开篇的命令,你可以看到结果的不同:

tput colors
## 这个时候返回的应该是256
echo $TERM
## 此时返回的应该是xterm-256color

此时,在开启Emacs,就会发现,可恶的终于得到了拯救。

其实你也可以在修改前后对比下Emacs内输入M-x list-colors-display(看不明白?可参看Emacs快捷键对照说明),看看前后的效果。——应该明显不同哦(8个颜色和256个颜色)

TIPS:

1. 如果上述修改后,没有得到正确的结果,说明你可能需要安装ncurses-term包来提供xterm-256color类型支持。里面有许多附加的终端类型定义。

2. 这种方法只能让PuTTY支持256色,如果你的Emacs还是显示的不符合你胃口,那么你就要考虑换配色方案了,而不是在这里寻找原因。

##在Emacs里面的minibuffer(小缓冲区域)内输入下面的命令,你就可以看到各种Themes了
## Mitchell觉得manoj-dark,tango-dark,tsdh-dark都还不错
M-x customize-themes RET

Emacs的常用快捷键功能对照表

MitchellChu 2014-05-12 其他技术

Emacs的功能非常多而且复杂,在的shell下使用的时候,如果不能够灵活使用快捷键,很多操作不可能顺利完成,正因为这一点,本文罗列了一些在Emacs下常用的快捷键组合。这样可以让Emacs的初学者——比如MitchellChu,可以比较快速的上手Emacs。

这篇文章中的快捷键提取自的帮助文档中,因此,在不方便联网的时候,你也可以通过帮助文档来获取同样的信息。

本文中出现的键值简写说明:

  1. Ctrl,CTL,C均表示为同一个功能键(普通键盘中的CTRL键);
  2. META,EDIT,ALT,M均表示为同一个键(常用键盘中的ALT键);
  3. SHITF,S均表示同一个键(键盘中的Shift键);
  4. ESC表示键盘中的ESC键;
  5. SPC表示键盘中的Space键(键盘中最长的那根空格键);
  6. Deletespace,Backspace意为同一个键(Backspace键);
  7. RET,ENTER表示同一个键(回车)。

本文中出现的组合键说明:

  1. [C-x]类型,短横线分隔表示同时按下。表示按下CTRL键之后,在不松开CTRL的前提下,按下x键。
  2. [C-x,o]类型,逗号分隔表示依次按下。按下CTRL键后,再按下x键(同上),之后松开所有键,再按o键;

快捷键类型说明:

  1. C-x是字符扩展:C-x之后输入一个另一个字符或者组合键,来达到执行新的命令的目的。
    如:C-x,C-c,这个就是接组合键的扩展,作用是退出Emacs
  2. M-x是命令名扩展:M-x之后输入的是一个命令名称。
    如:M-x customize-variable 则属于命令扩展, M-x replace-string 也属于命令扩展

 Emacs常用

快捷键 快捷键备注
M-w Save the region as if killed, but don't kill it.复制选中内容
C-w Kill ("cut") text between point and mark.剪切选中内容,见C-@
C-y Reinsert ("paste") the last stretch of killed text.粘贴内容
C-x,C-c 退出Emacs
C-v 下一屏
M-v 上一屏
C-l 重新定位光标位置,C-L可以将光标轮流切换为屏幕中部,屏幕顶部,和屏幕尾部三个位置.[C-u,0,C-l] 将光标位置至于顶行
C-p 光标上移一行(同向上方向键),p = previous
C-b 光标左移(同左方向键),b = backward
C-f 光标右移,f = forward
C-n 光标下移,n = next
M-f 向前移动一个词的位置,注意:在英文中,是以单词为跳跃跨度,在中文则是以标点符号(含空格)为跳跃跨度。
M-b 向后移动一个词的位置,注意:同上
C-a 移动到行首
C-e 移动到行尾
M-a 移动到句首,注意:一行可能存在多个句子,一句也可以跨越多行。
M-e 移动到句尾
M-< 移动到所有文本的最开头(本例在一般的键盘下可能是用[ALT+SHIFT+,]完成)
M-> 移动到所有文本的最末端
C-h Emacs的帮助文档命令,如果在有的主机上这个命令被改变意义,没有办法正常调用出帮助文档,可以尝试F1,[M-x,help]来尝试查看帮助文档
C-h,m 查看Emacs各个模式的说明,并可参看各个模式的异同
C-h,i 阅读联机手册(通常讲的Info),Emacs Info是使用Emacs的主要参考文档,如果不清楚如何使用,可以进入后按"?",Emacs的使用手册是m emacs.
C-h,C-h 帮助命令的帮助,关于C-h命令的用法
C-h,k,C-f 关于C-f的命令帮助信息
C-u,num C-u命令之后,输入数值,而后再输入命令,Emacs将会自动把数值传递到后面的命令,改变后面命令的行为,比如:[C-u,8,C-f]将能实现将贯标向右移动8个位置,相当于按了8次C-f。[C-u,8,C-v]不是向后移动了8屏,而是向后移动了8行,还有其他命令也会有可能有不同的功能。[C-u,8,*]将重复输入8个*.
ESC,ESC,ESC 取消ESC,多次ESC有的时候也可以用作取消(退出)当前命令执行。比如:在递归编辑中,C-g命令并不能一次完成取消(可能无效),此时多次按ESC就可用于快速退出递归编辑。
C-g 可用来取消Emacs长时间无响应的命令,或者输入到一半的命令。Esc之后,按C-g也能取消,但此时相当于按了[C-M-g],没有这个命令.
C-x,C-l 为防止初学者错误使用命令,Emacs禁用了一些命令,其中这个即是被禁用的命令,当按下之后,Emacs会提示是否启用,有可用的选项[y,n,!,SPC],y表示启动,并且以后使用这个命令不再询问;n表示取消本次调用;!执行本次命令,并且在当前会话内取消所有禁用的命令;SPC(空格)执行此命令,之后后,此命令依然被禁用,下次调用同样需要询问。
C-x,num 只保留num个窗口,如:C-x,1只保留一个窗口,该窗口为光标所在的窗口,并将窗口扩展到整个Emacs屏幕
Delback Backspace键,在编辑文本的时候,这个是删除光标前的一个字符
C-d 删除光标后的一个字符
M-Delback 移除光标前的一个词,注意:中文的词是用标点符号作为分隔
M-d 移除光标后的一个词
C-k 移除从光标到"行尾"间的所有字符,第一次操作不包含换行符,如果使用[C-u,2,C-k]的话,则自动会将换行符移除,和两次按C-k的效果不一样。k=kill。
M-k 移除从光标到"句尾"的字符,注意:移除(kill)可以被召回(yanking),但是删除(delete)就不可能被召回。但同时也请注意,召回和Undo(撤消)不一样。见下面C-y。
C-@/C-SPC 标记起始位置,两个组合键是同样的功能,但在中文环境中,C-SPC通常用来切换输入法,所以建议使用C-@。标记完成后,可以将光标移动到其他位置(使用移动光标的快捷键),之后输入C-w,即可完成C-@到结束位置的内容删除操作。
C-y,[M-y] 召回移除的内容,如果仅按C-y则是召回最后一次移除的内容,如果C-y后,按M-y,则是召回倒数第二次的内容,每多按一次M-y,则召回的内容是之前召回内容的前一条移除内容。注意:M-y是循环显示可召回的内容,因此到达第一条被移除的内容时再按M-y则显示最后一条移除内容。
C-x,u 撤消,撤消上一次命令所造成的改变。多次使用可依次撤消多次以前执行的命令。注意:没改变文字的命令不再撤消之列;键盘输入的字符此命令会自动以20个字符进行分组处理,不单个字符进行撤消。这个命令还可以使用[C-_]或则[C-/]来操作——主要以方便操作为原则,效果一样。可用[C-u,num,C-x,u]表示撤消操作次数。
C-x,C-f 寻找一个文件,命令输入完后,Emacs会提示输入文件名(屏幕最底端一行,此行也被称为小缓冲minibuffer),输入文件名后,回车即可打开文件。如果查找的文件不存在,则创建新文件(在保存的时候创建)
C-x,C-f 当打开多个文件之后,要进行文件间进行切换,可以使用此命令来进行——相当于再次打开(但此时在缓冲区内),也可以参见[C-x,b]。
C-x,C-b 列出缓冲区缓冲的文件列表,[C-x,C-f]每寻找到一个文件,Emacs就会在内部开辟一个缓冲区。
C-x,b 切换回某个缓冲区,此命令后面必须跟缓冲区名称。假设,myfile已经存在于Emacs的缓冲区内,则[C-x,b,myfile]是切换到myfile的缓冲区,此时界面上应该是现实myfile的内容。
C-x,s 保存缓冲区内的所有缓冲文件,Emacs会找出缓冲区内已修改但未保存的文件,然后逐个向你询问是否需要存盘。
C-x,C-s 存盘,存储当前操作的文件。
C-x,k Kill(关闭)一个缓冲区,这时候会要求输入名称,输入要关闭的文件名称即可关闭文件
C-x,C-v Kill当前缓冲并打开另外一个文件
C-x,i 插入一个文件到缓冲区
C-x,C-w 将缓冲另存为其他文件.
C-z 挂起Emacs,在Shell中,可以通过fg或者[%emacs]命令再次回到Emacs中。如果系统没有提供挂起功能,则Emacs会创建一个子shell,让你运行其他程序,这时可以通过在shell中exit来从子shell中返回Emacs。
M-x,replace-string 替换编辑区内的字符串,这个是命令扩展,后继会需要输入要被替换的原字符串,和要替换的目标串。
M-x, recover file 恢复自动保存的文件,Emacs会自动保存编辑中的文件(文件名是以#号开头并以#号结束),在某些非正常情况下退出Emacs后,可以再次进入Emacs,通过此命令恢复编辑中的文件。
M-x,text mode 将主模式切换成text模式, M-x fundamental-model切换到Fundamental模式。主模式都是可以通过M-x启动的扩展命令。不同的模式,同样的命令可能会有不同的执行效果。
M-x auto fill mode 启动自动折行模式——在字符超过一行边界时自动换行,这种模式为辅模式。如果当前已经启动了自动折行模式,则使用这个命令是关闭自动折行模式。换行的前提是有空格(中文不必)。
C-x f 传递参数(数字)来设置行边界,也可以通过[C-u,70,C-x,f]来达到同样的效果。
*M-q 在启用自动折行模式后,可以手动折叠重新折叠行。
C-s/C-r 搜索词,C-s是从当前位置向前搜索, C-r是向后搜索。Enter结束搜索,C-g取消搜索。当在找到搜索词的时候,再次按下搜索组合键,是查找下一个匹配词。C-g之后,光标在原位置,Enter后,光标是在搜索结果上。
C-x,o 在多窗口间切换光标。
C-M-v 向下滚动其他窗口屏幕(多个窗口时,只有其中一个会滚动)
C-M-S-v 向上滚动其他窗口屏幕
C-h,v,a-variable,RET 获得变量的帮助信息,如:[C-h,v,color-name-rgb-alist,RET]此时显示的是color-name-rgb-alist变量的信息
C-h,f,a-variable,RET 获得函数的帮助信息,如:[C-h,f,add-to-list,RET],此时Emacs显示add-to-list函数的帮助信息
C-h,i,m,elisp,RET 打开整个Emacs Manual后,进入Elisp的Manual

 

Linux下修改命令行终端显示的分辨率(tty)

MitchellChu 2014-05-11 Unix & Linux

以前写过一个Ubuntu下设置自定义桌面的分辨率的文章,使用的是xrandr和cvt,这次碰到的是要在下调整命令行终端的显示。在VMWare中CentOS的命令行终端(tty)默认是很小的(80x25),在偌大的显示屏(1920X1080)中显示出来就中间一小块。所以要解决的问题就是想办法将屏幕展开。

毫不犹豫的使用老方法——尝试xrandr命令,遗憾的是默认是没有的——没有X窗口系统嘛,就连cvt这个命令也没有踪影。

一招不行,再祭一招,修改grub.conf文件!通过修改grub.conf文件中kernel行——在最后加上vga参数,让系统在启动的时候能够自动加载适用的分辨率,如下面这样:

# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/mapper/vg_mitchell-lv_root
#          initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.32-431.5.1.el6.i686)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-431.5.1.el6.i686 ro root=/dev/mapper/vg_mitchell-lv_root rd_NO_LUKS rd_NO_MD rd_LVM_LV=vg_mitchell/lv_swap crashkernel=auto LANG=zh_CN.UTF-8 rd_LVM_LV=vg_mitchell/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet vga=365
        initrd /initramfs-2.6.32-431.5.1.el6.i686.img
title CentOS (2.6.32-358.el6.i686)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-358.el6.i686 ro root=/dev/mapper/vg_mitchell-lv_root rd_NO_LUKS rd_NO_MD rd_LVM_LV=vg_mitchell/lv_swap crashkernel=auto LANG=zh_CN.UTF-8 rd_LVM_LV=vg_mitchell/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
        initrd /initramfs-2.6.32-358.el6.i686.img

vga=分辨率的编号(Mode ID),这简单了,也妥帖了,写个数字就把你的分辨率搞定,可讲起来非常简单,就是添加个vga参数,加个数值而已,但这个数值是什么呢?网上绝大部分的筒子们都是给出一个列表,类似下面这样的一个表:

Graphics modes 320×200 640×400   640×480 800×600 1024×768 1280×1024
16-color palette       258 (0102h), 106 (6Ah) 260 (0104h) 262 (0106h)
256-color palette   256 (0100h) 257 (0101h) 259 (0103h) 261 (0105h) 263 (0107h)
15-bit (5:5:5) 269 (010Dh)   272 (0110h) 275 (0113h) 278 (0116h) 281 (0119h)
16-bit (5:6:5) 270 (010Eh)   273 (0111h) 276 (0114h) 279 (0117h) 282 (011Ah)
24-bit (8:8:8) 271 (010Fh)   274 (0112h) 277 (0115h) 280 (0118h) 283 (011Bh)

一看,就是找个数字,直接填写个数字作为vga的值就了事,不错!可仔细一看,这个表中竟然没有我要的,这让我情何以堪。在没有参数的情况下,自然就想知道这个数字是怎么出来的,所以接下来,目标就是去找这个列表出来的出处。

谷歌和度娘没少用,可是所有分辨率还是基本都在使用xrandr——这让我清醒的认识到这将是一个多么冷门的想法。。。

再后来的事情就是看到vga参数可以写成

vga=ask

这个设置是让系统启动的时候,可以显示所有本地显卡支持的分辨率。这可比直接写数字好很多,至少知道有这个方法可以知道本地机器支持的分辨率选项了,即使写数字,通过上面给出的Mode ID,我也能够设置vga参数值了。但如果一直使用ask,问题就是每次系统启动的时候都需要我们做选择,不做选择就回到原来那一小块膏药似的界面上去。这个解决的方法就是每次都按ENTER进入设置咯。如果不愿意,第一次选择好合适的分辨率,通过按a进入对应的kernel行编辑,其实就是将vga=ask修改成对应的Mode ID。

另外一个问题是,这种情况是要在系统启动的时候设置,如果想在系统内设置,就没有办法了。好吧,Mitchell个人更希望能在系统内部直接设置好,虽然上面启动的时候设置已经很好了,继续找找能不能在系统内部设置。

最后,发现vga=ask的时候,启动屏幕的选择列表上有VESA(Video Electronics Standards Association)字样,按图索骥,发现其中的一个VESA的标准是VESA BIOS Extensions(VBE)。——对于菜鸟的我来说,这是多么深奥的一个词!干嘛用的?——不知道。

但在VESA BIOS Extensions的WIKI页面1,看到有SVGA2的也一个页面,查看了SVGA.txt之后,才发现:

This small document describes the "Video Mode Selection" feature which
allows the use of various special video modes supported by the video BIOS. Due
to usage of the BIOS, the selection is limited to boot time (before the
kernel decompression starts) and works only on 80X86 machines.

这... 这节奏的意思就是,要在系统内调用这个菜单设置是完全没有办法了啊!但我要的列表的呢?咋也没有呢?

不甘放弃,后来经过艰苦的寻找(没方向真是艰苦),找到工具hwinfo,这个Linux下的工具可以查找BOIS信息,同时可以通过--framebuffer参数查找到系统支持的分辨率,方法如下:

hwinfo --framebuffer |grep Mode

只需要--framebuffer里面的Mode信息,显示的结果类似下面这样:

  Model: "VMware virtual machine"
  Mode 0x0300: 640x400 (+640), 8 bits
  Mode 0x0301: 640x480 (+640), 8 bits
  Mode 0x0303: 800x600 (+800), 8 bits
  Mode 0x0305: 1024x768 (+1024), 8 bits
  Mode 0x0307: 1280x1024 (+1280), 8 bits
  Mode 0x030e: 320x200 (+640), 16 bits
  Mode 0x0311: 640x480 (+1280), 16 bits
  Mode 0x0314: 800x600 (+1600), 16 bits
  Mode 0x0317: 1024x768 (+2048), 16 bits
  Mode 0x031a: 1280x1024 (+2560), 16 bits
  Mode 0x0320: 320x200 (+320), 8 bits
  Mode 0x0321: 320x400 (+320), 8 bits
  Mode 0x0322: 640x400 (+640), 8 bits
  Mode 0x0323: 640x480 (+640), 8 bits
  Mode 0x0324: 800x600 (+800), 8 bits
  Mode 0x0325: 1024x768 (+1024), 8 bits
  Mode 0x0326: 1152x864 (+1152), 8 bits
  Mode 0x0327: 1280x960 (+1280), 8 bits
  Mode 0x0328: 1280x1024 (+1280), 8 bits
  Mode 0x0329: 1400x1050 (+1408), 8 bits
  Mode 0x032a: 1600x1200 (+1600), 8 bits
  Mode 0x032b: 1792x1344 (+1792), 8 bits
  Mode 0x032c: 1856x1392 (+1856), 8 bits
  Mode 0x032d: 1920x1440 (+1920), 8 bits
  Mode 0x032e: 320x200 (+640), 16 bits
  Mode 0x032f: 320x400 (+640), 16 bits
  Mode 0x0330: 640x400 (+1280), 16 bits
  Mode 0x0331: 640x480 (+1280), 16 bits
  Mode 0x0332: 800x600 (+1600), 16 bits
  Mode 0x0333: 1024x768 (+2048), 16 bits
  Mode 0x0334: 1152x864 (+2304), 16 bits
  Mode 0x0335: 1280x960 (+2560), 16 bits
  Mode 0x0336: 1280x1024 (+2560), 16 bits
  Mode 0x0337: 1400x1050 (+2816), 16 bits
  Mode 0x0338: 1600x1200 (+3200), 16 bits
  Mode 0x0339: 1792x1344 (+3584), 16 bits
  Mode 0x033a: 1856x1392 (+3712), 16 bits
  Mode 0x033b: 1920x1440 (+3840), 16 bits

.........more................

 这个出来的结果符合我的期望,这样就能直接在系统内部进行设置vga参数了,为了偷懒,写了个脚本,来提取信息:

###################################################
##
## Linux system terminal resolution utility
## Create by MitchellChu @2014.05.10
##
###################################################
#get system type
SysType=`cat /etc/issue|awk 'FNR==1{print tolower($1)}'`
#get hardware's framebuffer data and filter framebuffer information, then format it.
sudo hwinfo --framebuffer 2>/dev/null |grep "Mode\s*0x" | awk 'BEGIN{print "ModeID:Resolution-depth\t\tModeID:Resolution-depth"} {
output = (substr($2, 1, 6)+0)":"$3"-"$5$6
if(FNR%2==0) printf "%s\n", output; else printf "%s\t\t", output;}'
read -p "Please enter your mode id:" resolutionModeId
read -p "you choiced mode id is:$resolutionModeId, are you sure (y|n)?:" uconfirm
if [ "${uconfirm,,}" = 'y' ]; then
  case $SysType in
    "ubuntu") echo "ubuntu system..."
      sudo sed -i "s/^\s*linux\s.*$/& vga=$resolutionModeId/" /boot/grub/grub.cfg;;
    "centos") echo "CentOS system..."
      sudo sed -i "s/^\s*kernel\s.*$/& vga=$resolutionModeId/" /boot/grub/grub.conf;;
    "debian") echo "Debian system..."
      sudo sed -i "s/^\s*linux\s.*$/& vga=$resolutionModeId/" /boot/grub/grub.cfg;;
    *) echo "undetected system..."
      echo "the script unsupported current system.";;
  esac
else
  echo "Not file be updated."
fi
echo "script works done. you can reboot to enable new config."

这样将代码保存为脚本,在需要修改分辨率的时候,运行脚本就能获取系统支持的系统分辨率。

到此,总算不是很完美的达到了在系统运行的时候设置vga参数。为什么说不完美?因为CentOS下是没有hwinfo的,为了实现这个我们必须要手动去安装hwinfo(或者其他类似工具)。个人开始是希望从内存中直接读取BIOS的数据来获取显卡支持的分辨率,下面是个尝试之一:

sudo dd if=/dev/mem bs=1K skip=768 count=256 2>/dev/null | strings -n 8

但是由于不知道这些设置在内存中的位置,也不清楚BIOS在内存中的格式——个人猜想每个系统里BIOS保存的内存地址应该也会有差别。因此只能作罢。

 

TIPS:本文仅是个人作为对系统分辨率修改的一种尝试,菜鸟一枚,欢迎大家拍砖!

同时也注意,在某些情况下设置vag参数并不能达到我们需要的效果,比如参考文章4中提及的情况。

 

参考文章: 

 1. VESA BIOS Extensions

2. SVGA

3. VESAFB

4. How to set the resolution in text consoles

终端上常用的及一些高级Shell命令汇总

MitchellChu 2014-05-09 Unix & Linux

在Linux下不像Windows下这样是鼠标的天下,主要的使用键盘啊亲,Shell命令的重要性自然不言而喻,然而Linux系统那么多的Shell命令,有些让人应接不暇,这种情况下,就只能记住一些常用的,有用的命令了 —— 本文记录就是这样一些

System
运行中的kernel和system信息
uname -a ## 获取kernel版本(和BSD版本)
lsb_release -a ## 打印本系统发行版的所有信息,比如发行版的ID,描述信息,具体版本,代号。LSB (Linux Standard Base)
cat /etc/debian_version ## 获取Debian 版本,Ubuntu:/etc/DISTR-release, DISTR= lsb。通用/etc/issue。
uptime ## 显示系统已经运行(加载)的时间
hostname ## 系统的主机名
hostname -i ## 显示本地主机的IP地址
man hier ## 描述文件系统的层次结构
last reboot ## 显示系统重启的历史记录
硬件信息
Kernel检测到的硬件
dmesg ##检测到的硬件和启动信息
lsdev ## 已经安装的硬件信息
dd if=/dev/mem bs=1k skip=768 count=256 2>/dev/null | strings -n 8 ## 读取 BIOS
cat /proc/cpuinfo ## CPU model
cat /proc/meminfo ## 硬件中内存的信息
grep MemTotal /proc/meminfo ## 显示系统的物理内存
watch -n1 'cat /proc/interrupts' ## 连续动态监测中断状态
free -m ## 已经使用和空闲内存(m=MB)
cat /proc/devices ## 已配置的设备
lspci -tv ## PCI设备
lsusb -tv ## USB设备
lshal ## 显示所有设备的属性清单
dmidecode ## DMI/SMBIOS: 来自BIOS的硬件信息
Load, statistics 和 messages
下面的命令在找出运行于系统上的程序信息非常有用.
top ## 动态显示cpu进程信息
mpstat 1 ## 进程的相关统计信息
vmstat 2 ## 虚拟内存统计信息
iostat 2 ## I/O统计信息 (2s间隔)
systat -vmstat 1 ## BSD系统统计汇总 (1s)
systat -tcp 1 ## BSD tcp 连接 (也可 -ip)
systat -netstat 1 ## BSD 活动的网络连接
systat -ifstat 1 ## BSD 通过活动的网络接口的网络流量
systat -iostat 1 ## BSD CPU和磁盘的吞吐量
tail -n 500 /var/log/messages ## 最后500条kernel/syslog信息
tail /var/log/warn ## 系统警告信息,参看:syslog.conf
用户类
系统下关于用户信息的各种Shell命令
id ## 当前活动帐户的用户ID的相关信息
last ## 系统的最近的登录记录
who ## 系统当前登录的所有用户
groupadd admin ## 添加admin组
useradd -c "Mitchell Chu" -g admin -m mitchell ## 添加mitchell用户,并将mitchell添加到admin组
usermod -a -G ## 添加现存用户到组 (Debian)
userdel mitchell ## 删除用户mitchell 
pw groupmod admin -m newmembe r ## 添加新成员到组
pw useradd mitchell -c "Mitchell Chu" -g admin -m -s /bin/tcsh ## 
pw userdel mitchell; pw groupdel admin ## 
Kernel模块
内核模块信息
lsmod ## kernel加载的所有模块
modprobe isdn ## 加载模块 (这里是isdn)
Kernel编译
内核编译命令
cd /usr/src/linux
make mrproper # 清除所有,删除不必要的文件和目录,包括配置文件
make oldconfig # 如果存在老配置文件(.config)则重用
make menuconfig # 基于文本选单的配置界面,字符终端下推荐使用, xconfig (Qt) or gconfig (GTK),(需要安装ncurses)
make # 创建一个压缩的kernel image
make modules # 编译modules
make modules_install # 安装modules
make install # 安装kernel
reboot
grub修复
当grub出现损坏时,通过live cd来启动,(在/dev下找到linux分区,然后使用fdisk来找到这个Linux分区)挂载这个linux分区,添加/proc和/dev并使用grub-install /dev/xyz。假设Linux系统位于/dev/sda4.
mount /dev/sda6 /mnt # 将linux分区挂载到/mnt
mount --bind /proc /mnt/proc # 挂载proc subsystem到/mnt
mount --bind /dev /mnt/dev # 挂载devices到/mnt
chroot /mnt # 更改 root 目录
grub-install /dev/sda # 使用旧配置重新安装grub
Listing和PIDs
每个进程都有一个唯一的数字,PID。通过ps可以获取当前在运行的所有进程列表。当然,更典型的用法是和pipe或者pgrep一起使用来过滤信息。
ps -auxefw ## 所有运行中的进程列表
ps axww | grep cron ## 返回类似:586 ?? Is 0:01.48 /usr/sbin/cron -s
ps axjf ## 所有的进程使用树状格式显示
ps aux | grep 'ss[h]' ## 查找所有的进程ssh的PIDs,grep 条目不显示
pgrep -l sshd ## 通过名称(或部分名称)来查找进程的PIDs
echo $$ ## 当前shell的PID
fuser -va 22/tcp ## 列出使用端口号为22的进程 (Linux)
pmap PID ## 进程的Memory map(可用于搜索内存泄露) (Linux)
fuser -va /home ## 列出正在访问 /home的进程
strace df ## 追踪系统的 calls 和 signals
truss df ## 同上
Signals/Kill
通过kill或killall终止或发送一个信号。
kill -s TERM 4712 ## 同kill -15 4712
killall -1 httpd ## 用(详细)名称 Kill HUP 进程
pkill -9 http ## 用(部分)名称Kill 进程
pkill -TERM -u www ## Kill TERM 进程(属于用户www的)
fuser -k -TERM -m /home ## Kill 所有访问 /home 的进程(umount时可用)
重要的signals有:
1 HUP (hang up)
2 INT (interrupt)
3 QUIT (quit)
9 KILL (non-catchable, non-ignorable kill)
15 TERM (software termination signal)
Permissions(权限)
通过chmod和chown来修改权限和所有者信息。在Linux下,所有用户的默认的umask可以在/etc/profile下面修改。默认的umask通常是022。umask会从777中减去,因此022的umask表现在权限中的结果是755.
1 --x execute # Mode 764 = exec/read/write | read/write | read
2 -w- write # For: |-- Owner --| |- Group-| |Oth|
4 r-- read
ugo=a u=user, g=group, o=others, a=everyone
chmod [OPTION] MODE[,MODE] FILE ## MODE 应属于这种形式: [ugoa]*([-+=]([rwxXst]))
chmod 640 /var/log/maillog ## 限定日志为 -rw-r-----
chmod u=rw,g=r,o= /var/log/maillog ## 同上
chmod -R o-r /home/* ## 递归移除/home下所有其他用户的读权限
chmod u+s /path/to/prog ## 在可执行位置设置SUID位(确认你要这么做!!!这将改变euid和egid的值,处置不当将会带来很大安全风险,SGID有时候是更好的选择)
find / -perm -u+s -print ## 查找所有设置了SUID位的程序
chown user:group /path/to/file ## 更改文件的所属用户和组(user,group要存在)
chgrp group /path/to/file ## 更改文件所属组
chmod 640 `find ./ -type f -print` ## 修改所有文件的权限为: 640
chmod 751 `find ./ -type d -print` ## 修改所有文件夹的权限为:751
Disk——磁盘信息
获取磁盘信息,系统挂载点/磁盘使用量
hdparm -I /dev/sda ## IDE/ATA 磁盘信息 (Linux)
fdisk /dev/ad2 ## 显示和更改当前的分区表
smartctl -a /dev/ad2 ## 显示磁盘的SMART信息
mount | column -t ## 显示系统已经挂载的文件系统(file-systems)
df ## 显示可用磁盘空间和已挂载的设备
cat /proc/partitions ## 所有已注册的磁盘分区
du -sh * ## 以列表形式显示目录的大小
du -csh ## 当前目录的总用量
du -ks * | sort -n -r ## 按千字节(kilobytes)大小排序项目
查看用户已经打开的文件信息
这个方法可以有效的找出阻止了要卸载分区并引起下面这个典型错误的文件。注意,umount利用设备名或挂载点都能卸载文件系统,不过最好还是使用挂载点进行,以免使用绑定挂载(一个设备,多个挂载点)时出现混乱。
#通过设备名卸载
umount -v /dev/sda1
#通过挂载点卸载
umount -v /mnt/my_mount_point
#如果设备正忙,则卸载失败,会报错umount: unmount of /mnt/my_mount_point failed: Device busy.
umount /home/
umount: unmount of /home failed: Device busy. ## umount impossible because a file is locking home
ls -lSr ## 显示所有文件,最大的在后面
## 通过fuser和lsof来查找挂载点打开的所有文件
fuser -m /home ## 列出所有访问/home的进程
lsof /home
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
tcsh 29029 eedcoba cwd DIR 0,18 12288 1048587 /home/cipi (cipi:/home)
lsof 29140 eedcoba cwd DIR 0,18 12288 1048587 /home/cipi (cipi:/home)
## 通过进程PID来使用lsof,需要先通过下面的这个方式来获得PID
ps ax | grep Xorg | awk '{print $1}'
3324
lsof -p 3324
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
Xorg 3324 root 0w REG 8,6 56296 12492 /var/log/Xorg.0.log
About a single file:
lsof /var/log/Xorg.0.log
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
Xorg 3324 root 0w REG 8,6 56296 12492 /var/log/Xorg.0.log
挂载或重新挂载文件系统
以cdrom为例,假设cdrom已经存在/etc/fstab,(在CentOS下,cdrom的添加在/etc/mtab下。下同)。进入/etc/fstab,可以看到类似下面的信息:
/dev/cdrom /media/cdrom subfs noauto,fs=cdfss,ro,procuid,nosuid,nodev,exec 0 0
mount /cdrom ## 存在于mtab的前提下
mount -t auto /dev/cdrom /mnt/cdrom ## 常用的cdrom挂载命令
mount /dev/hdc -t iso9660 -r /cdrom ## 常用的 IDE
mount /dev/scd0 -t iso9660 -r /cdrom ## 常用的 SCSI cdrom
mount /dev/sdc0 -t ntfs-3g /windows ## 常用的 SCSI
实时增加swap
假设现在需要更多的swap,例如一个2GB的文件 /swap2gb。注意:如果有多余分区,也可以使用分区来创建swap,swap最多能创建32个.
dd if=/dev/zero of=/swap2gb bs=1024k count=2000
mkswap /swap2gb ## 创建swap区域
swapon /swap2gb ## 激活这个swap,现在就可以使用了
swapoff /swap2gb ## 当完成后,取消swap
rm /swap2gb ## 删除swap
挂载一个SMB共享
假设我们想访问计算机smbserver上的SMB共享myshare,在Windows上地址为:\\smbserver\myshare\. 我们直接挂载到/mnt/smbshare。会出现警告:Warning> cifs wants an IP or DNS name, not a Windows name.
smbclient -U user -I 192.168.16.229 -L //smbshare/ ## 列出共享
mount -t smbfs -o username=winuser //smbserver/myshare /mnt/smbshare
mount -t cifs -o username=winuser,password=winpwd //192.168.16.229/myshare /mnt/share
注意:使用mount.cifs包,这可能会将credentials保存到文件中,比如:/home/user/.smb:
username=winuser
password=winpwd
然后再进行mount
mount -t cifs -o credentials=/home/user/.smb //192.168.16.229/myshare /mnt/smbshare
挂载一个image
image不是图片,是镜像.
mount -t iso9660 -o loop file.iso /mnt ## 挂载CD image
mount -t ext3 -o loop file.img /mnt ## 以ext3文件系统格式挂载image
创建一个内存文件系统
对于高IO负载的应用程序来说,基于内存的文件系统是非常快的.下面例子展示如何创建一个挂载到/memdisk的64MB分区。
mount -t tmpfs -osize=64m tmpfs /memdisk
磁盘性能
下面例子展示在分区ad4s3c(/home)读写1GB的文件。
time dd if=/dev/ad4s3c of=/dev/null bs=1024k count=1000
time dd if=/dev/zero bs=1024k count=1000 of=/home/1Gb.file
hdparm -tT /dev/hda ## 仅Linux
网络
网络的一些有用功能
ethtool eth0 ## ethernet的状态(eth0) (替换:mii-diag)
ethtool -s eth0 speed 100 duplex full ## 强制使用100Mbit 全双工(Full duplex)
ethtool -s eth0 autoneg off ## 关闭(禁用)自动协商
ethtool -p eth1 ## 闪烁ethernet的led - 如果支持的情况下这个功能非常有用
ip link show ## 显示Linux上的所有的接口 (类似 ifconfig)
ip link set eth0 up ## 启用或关闭设备. 同 "ifconfig eth0 up"
ip addr show ## 显示Linux上的所有的IP地址 (类似 ifconfig)
ip neigh show ## 类似 arp -a
使用中的端口
当前处于打开状态的端口号
netstat -an | grep LISTEN
lsof -i ## 列出所有的互联网连接
socklist ## 显示所有打开的socket列表
netstat -anp --udp --tcp | grep LISTEN 
netstat -tup ## 列出所有活动的连接(连接到/连接自当前系统的)
netstat -tupl ## 列出所有本地监听的端口
防火墙
首先确保防火墙已经运行,这里给出的是一般的配置。
iptables -L -n -v ## iptables防火墙已启用规则列表的详细信息
iptables -P INPUT ACCEPT ## INPUT的默认策略改为ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -Z ## 清零所有链上的包和字节计数器
iptables -F ## 清除所有链规则
iptables -X ## 删除所有用户定义的链
路由IP Forward
检查并且启用IP转发
cat /proc/sys/net/ipv4/ip_forward ## 检查IP forward设置,0=off, 1=on
echo 1 > /proc/sys/net/ipv4/ip_forward
或者编辑:/etc/sysctl.conf
net.ipv4.ip_forward = 1
网络地址转换(NAT)
利用IPTABLE来做网络地址转换。MASQUERADE模块需要加载.
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE ## 激活NAT
iptables -t nat -A PREROUTING -p tcp -d 78.31.70.238 --dport 20022 -j DNAT \
--to 192.168.16.44:22 ## 将端口20022转到内网IP的SSH端口
iptables -t nat -A PREROUTING -p tcp -d 78.31.70.238 --dport 993:995 -j DNAT \
--to 192.168.16.254:993-995 ## 转换端口范围:993-995
ip route flush cache
iptables -L -t nat ## 检查NAT状态
DNS
DNS条目存放在/etc/resolv.conf下面,针对本地所有的网络接口有效.下面是可能的最小配置:
nameserver 66.63.128.84
search cipi.net intern.lab
domain cipi.org
如果要检查系统的域名可以这样:
hostname -d ## 这里和DNS Domain name一致
DHCP
DNS条目存放在/etc/resolv.conf下面,针对本地所有的网络接口有效.下面是可能的最小配置:
dhcpcd -n eth0 ## 触发下renew(注意并不是每次都能正常工作)
dhcpcd -k eth0 ## release并且shutdown
续租的详细信息被存放在:/var/lib/dhcpcd/dhcpcd-eth0.info
tar
命令tar(磁带归档,tape archive)创建和提取文件和目录的归档。.tar归档文件是没有压缩的,压缩的归档文件一般会有.tgz,.tar.gz(zip),.tbz(bzip2)的后缀。在创建归档时请不要使用绝对路径,因为提取文件时你可能会需要放到其他的地方。
## 创建
cd /
tar -cf home.tar home/ ## 归档整个/home目录 (c参数用来创建按)
tar -czf home.tgz home/ ## 和zip压缩一样
tar -cjf home.tbz home/ ## 和bzip2压缩效果一样
## 多个目录时,保留目录的结构,下面的这个是/usr/local/etc和/usr/local/www归档,保持相对的目录结构,最后的归档文件是local开始
tar -C /usr -czf local.tgz local/etc local/www
tar -C /usr -xzf local.tgz ## untar local目录到/usr
cd /usr; tar -xzf local.tgz ## 同上
## 提取
tar -tzf home.tgz ## 不提取文件仅仅是查看归档文件列表
tar -xf home.tar ## 提取文件到当前目录(x参数是提取)
tar -xzf home.tgz ## 同zip解压(bzip2是-xjf)
## 移除路径的起始gallery2并提取到gallery目录下
tar --strip-components 1 -zxvf gallery2.tgz -C gallery/
tar -xjf home.tbz home/mitchell/file.txt ## 恢复单个文件
## 更多高级货
tar c dir/ | gzip | ssh user@remote 'dd of=dir.tgz' ## 归档dir/并保存到远端.
tar cvf - `find . -print` > backup.tar ## 归档当前目录
tar -cf - -C /etc . | tar xpf - -C /backup/etc ## 拷贝目录
tar -cf - -C /etc . | ssh user@remote tar xpf - -C /backup/etc ## 远程拷贝
tar -czf home.tgz --exclude '*.o' --exclude 'tmp/' home/ ## 剔除文件和目录
Find
Find的一些重要的选项:
-x (BSD下) -xdev (Linux系统) ## 保持在同一文件系统 (dev在fstab里).
-exec cmd {} \; ## 执行cmd命令并用全路径替换{}
-iname ## 类似于 -name,不同在于它是大小写不敏感,ignorecasename
-ls ## 显示文件的信息 (类似于 ls -la)
-size n ## n 值为 +-n (k M G T P)
-cmin n ## 文件的状态在过去的n分钟内被修改过
find . -type f ! -perm -444 ## 查找所有不可读的文件
find . -type d ! -perm -111 ## 查找不可访问的所有目录
find /home/user/ -cmin 10 -print ## 查找在过去10分钟内创建或修改过的文件
find . -name '*.[ch]' | xargs grep -E 'expr' ## 在目录内或子目录内查找'expr'.
find / -name "*.core" | xargs rm ## 查找内核的转储并删除 (也可尝试 core.*)
find / -name "*.core" -print -exec rm {} \; ## 执行其他语法
## 查找图片并创建归档, iname大小写不敏感. -r 为附加
find . \( -iname "*.png" -o -iname "*.jpg" \) -print -exec tar -rf images.tar {} \;
find . -type f -name "*.txt" ! -name README.txt -print ## 执行 README.txt
find /var/ -size +10M -exec ls -lh {} \; ## 查找 > 10 MB的文件
find /var/ -size +10M -ls ## 这是更简单的版本
find . -size +10M -size -50M -print
find /usr/ports/ -name work -type d -print -exec rm -rf {} \; ## 清理端口
## 通过SUID来查找文件; 这些文件非常容易受到攻击,必须保证其安全性
find / -type f -user root -perm -4000 -exec ls -l {} \;
杂项
系统里一些其他有用的命令
which command ## 显示命令的全路径
time command ## 查看命令执行的时间
time cat ## 用time当作码表(stopwatch). Ctrl-c退出
set | grep $USER ## 显示当前的环境变量
cal -3 ## 显示一个三个月的日历
date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
date 10022155 ## 设置日期和时间
whatis grep ## 显示命令或词的简短信息
whereis java ## 查找提供的词的路径和标准目录
setenv varname value ## 设置环境变量varname的值为value (csh/tcsh)
export varname="value" ## 同上 (sh/ksh/bash)
pwd ## 输出工作目录
mkdir -p /path/to/dir ## 存在目录不报错必要时创建父目录
mkdir -p project/{bin,src,obj,doc/{html,man,pdf},debug/some/more/dirs}
rmdir /path/to/dir ## 删除目录
rm -rf /path/to/dir ## 强制删除目录和目录下的内容(force)
rm -- -badchar.txt ## 删除以中划线开头的文件 (-)
cp -la /dir1 /dir2 ## 存档和硬链接文件,来替代拷贝
cp -lpR /dir1 /dir2 #
cp unixtoolbox.xhtml{,.bak} ## 拷贝有多个扩展名的文件的快捷方式,包含unixtoolbox.xhtml
mv /dir1 /dir2 ## 重命名
ls -1 ## 一行一个文件名
history | tail -50 ## 显示历史中最后50个命令
cd - ## cd 转到之前的那个目录 ($OLDPWD)
添加/删除程序
针对Debian/Ubuntu/Mint
apt-get update ## 更新包列表
apt-get install emacs ## 安装emacs包
dpkg --remove emacs ## 删除emacs
dpkg -S file ## 查找文件所属包

CentOS下编译安装Python2.7.6

MitchellChu 2014-05-07 Unix & Linux

下面Python在升级到2.7.6的时候,没有找到安装包直接安装,只能通过源代码编译的方式来安装Python 2.7.6版本。这篇是编译和安装Python2.7.6的过程记录。

CentOS系统中安装了development tools。Python,执行下面代码:

$ pushd /usr/local/src
$ sudo mkdir python
$ sudo chown $USER python
$ cd python
$ wget https://www.python.org/ftp/python/2.7.6/Python-2.7.6.tgz
$ tar zxvf Python-2.7.6.tgz
$ cd Python-2.7.6
$ ./configure --prefix=/usr/local/python-2.7.6 &&
make
$ sudo make install

代码过程:

1. 在/usr/local/src创建文件夹,并将Python文件夹所有者设置为当前用户(非root)

2. 进入创建的python目录下,从官方网站上下载python2.7.6源代码包。

3. (非必须)如果要校验包的一致性,可以在官方网站上下载sig文件,并通过PGP校验文件,也可以通过官网提供的MD5校验下载的压缩包。更多关于校验的信息请参考Linux下校验文件的完整性(MD5,SHA1,PGP)。本代码忽略了此过程。

4. 解压压缩包到当前目录,并进入Python-2.7.6目录

5. 配置python并编译。这步只是用了--prefix参数指示安装路径。

6. 安装Python [也可使用altinstall的安装方式,这样文件末尾会带上版本号。updated: 2015-07-13]

上面是在Python编译安装顺利的情况下的大体流程,但是我在编译的时候,Python出现了下面的提示信息:

Python build finished, but the necessary bits to build these modules were not found:
   _bsddb             _sqlite3           _ssl
   _tkinter           bsddb185           bz2
   dbm                gdbm               readline
   sunaudiodev
To find the necessary bits, look in setup.py in detect_modules() for the module's name.

当然,每个机器上因为不同的配置,编译报错信息也会不同,比如网上有人的报错就是下面这样的:

Python build finished, but the necessary bits to build these modules were not found:
   _bsddb             _curses            _curses_panel   
   _sqlite3           _ssl               _tkinter        
   bsddb185           bz2                dbm             
   dl                 gdbm               imageop         
   readline           sunaudiodev        zlib            
To find the necessary bits, look in setup.py in detect_modules() for the module's name.

无论报错信息如何,意思很明确,我们编译的时候,系统没有办法找到对应的模块信息,为了解决这些报错,我们就需要提前安装依赖包,这些依赖包对应列表如下(不一定完全):

模块 依赖 说明
_bsddb bsddb Interface to Berkeley DB library。Berkeley数据库的接口
_curses ncurses Terminal handling for character-cell displays。
_curses_panel ncurses A panel stack extension for curses。
_sqlite3 sqlite DB-API 2.0 interface for SQLite databases。SqlLite,CentOS可以安装sqlite-devel
_ssl openssl-devel.i686 TLS/SSL wrapper for socket objects。
_tkinter N/A a thin object-oriented layer on top of Tcl/Tk。如果不使用桌面程序可以忽略TKinter
bsddb185 old bsddb module 老的bsddb模块,可忽略。
bz2 bzip2-devel.i686 Compression compatible with bzip2。bzip2-devel
dbm bsddb Simple “database” interface。
dl N/A Call C functions in shared objects.Python2.6开始,已经弃用。
gdbm gdbm-devel.i686 GNU’s reinterpretation of dbm
imageop N/A Manipulate raw image data。已经弃用。
readline readline-devel GNU readline interface
sunaudiodev N/A Access to Sun audio hardware。这个是针对Sun平台的,CentOS下可以忽略
zlib Zlib Compression compatible with gzip

在CentOS下,可以安装这些依赖包:readline-devel,sqlite-devel,bzip2-devel.i686,openssl-devel.i686,gdbm-devel.i686,libdbi-devel.i686,ncurses-libs,zlib-devel.i686。完成这些安装之后,可以再次编译,上表中指定为弃用或者忽略的模块错误可以忽略。

 在编译完成之后,就可以接着上面的第六步安装Python到指定目录下。安装完成之后,我们可以到安装目录下查看Python是否正常安装。

$ pushd /usr/local/python-2.7.6/bin
$ python --version
$ sudo mv /usr/bin/python /usr/bin/python.old
$ sudo ln -s python /usr/bin/python
$ popd
$ python -V
$ sudo sed -i "s/#\!\/usr\/bin\/python/#\!\/usr\/bin\/python.old/" /usr/bin/yum

1. 我们进入到安装路径下的bin目录, 并查看安装的版本(版本是2.7.6)

2. 将现有的python版本重命名备份

3. 创建新版本Python到/usr/bin目录下替代原有python

4. 测试系统Python版本(应该是新的2.7.6)

5. 此时如果yum不能正常工作,可以简单的通过sed将里面的Python引用替换成原来的Python路径即可。

至此,完成Python的更新编译安装工作。如果你想完成自动安装,可以将前面的代码保存为Shell脚本文件——需要注意的是,你可能需要添加各个模块的安装脚本,本篇的是通过yum来安装的。也可以通过参考2中的文章,文中包含自动安装的脚本文件。

 

参考:

1.  Python官方网站

2.  Install Python 2.7.2 On CentOS 5.2,包含自动化安装脚本。

Linux(CentOS)下编译安装Nginx及配置多网站

MitchellChu 2014-05-01 Unix & Linux

下编译安装Nginx,比起其他程序来说相对简单些。以下是个人编译的一些记录。

Nginx,Mitchell添加了pcre和zlib两个参数,因此需要到官方网站上下载可用版本的源代码,由Nginx编译的时候,一并完成编译。

注意:要让配置文件中的location支持正则表达式或者要启用ngx_http_rewrite_module的时候,就需要使用PCRE。而要让Nginx能够启用gzip选项,就必须添加zlib。版本选择Nginx支持的最新版本即可。

$ ./configure \
   --prefix=/usr/local/nginx-1.6.0 \
   --pid-path=/usr/local/nginx-1.6.0/run \
   --user=nginx \
   --group=nginx \
   --with-http_ssl_module \
   --with-pcre=../pcre/pcre-8.3.2 \
   --with-zlib=../zlib/zlib-1.2.7 &&
make

在configure的参数中我们依次定义了安装路径,pid路径,运行的用户名,用户组名称,启用SSL,使用PCRE,Zlib。

如果./configure没有问题,那么接下来系统就会直接make。如果系统make之后也没有错误,就可以切换到root帐户下,将编译好的Nginx安装。

## 注意:安装必须要切到root帐户下面.
# make install

安装完毕之后,由于,这让我们可以直接先启动Nginx,确认Nginx已经成功安装。如果能够正常启动,我们就可以通过宿主的80端口(HTTP)访问到Nginx的欢迎页面了。

## 启动Nginx
# /usr/local/nginx-1.6.0/sbin/nginx

正常的情况下,此时Nginx是处于工作状态,并且界面没有任何回显。

需要注意:

1. 如果你没有创建./configure参数中的用户组和用户,是无法正常启动的;

2. 请在root下启动Nginx

3. Nginx宿主机的80端口需要确保没有被其他程序占用(如:Apache)

确认能正常启动后,我们可以在/usr/local/bin下创建一个软链接到nginx执行文件上,这样就不用每次都输入一长串的路径了。

# ln -fs /usr/local/bin/nginx /usr/local/nginx-1.6.0/sbin/nginx

创建Nginx软链完成后,我们尝试下关闭Nginx:

#nginx -s quit

Nginx配合-s参数,可以有如下指令:

stop —— 快速关闭;

quit —— 退出(关闭),这个会等待Nginx处理完当前请求;

reload —— 重新加载配置文件;

reopen —— 重新打开日志文件。

在Nginx成功编译安装之后,我们更进一步的可以配置下Nginx的配置文件,默认的配置文件在安装目录下的conf/nginx.conf(添加中文注释):

#user  nobody;
#设置工作进程数
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    #并发连接数,可以启用epoll
    worker_connections  1024;
}


http {
    include       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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;
    #开启gzip,如果编译安装的时候没有zlib,此项注释掉
    gzip  on;
    #网站配置
    server {
        # 监听端口,HTTP 80端口
        listen       80;
        # 主机名,有域名,绑定就可以了,多个用空格分隔
        server_name  localhost blog.useasp.net;
        #编码
        #charset koi8-r;
        #访问日志
        #access_log  logs/host.access.log  main;
        #网站位置配置
        location / {
            #根目录
            root   html;
            #默认页
            index  index.html index.htm;
        }

        #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   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;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

 如果是单个网站,直接修改server里面的配置就足以完成需要配置。如果涉及到的情况下,直接修改conf文件,在网站数量一多的情况下,可维护和可配置性就很差(上面默认的配置文档中,Nginx配置了三个网站,其中注释掉有两个,但复杂性已经显现)。为了更好的完成多网站的配置,我们可以将每一个网站的配置独立出来,然后以独立文件的形式统一放到一个目录下,在Nginx的配置文件nginx.conf中,只需要加载该目录下的所有配置文件即可。

首先修改Nginx的默认配置文档nginx.conf,将所有的网站配置节提取出来:

worker_processes  1;
events {
    worker_connections  1024;
}


http {
    # 这里我们只存放Nginx全局的配置项
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    gzip  on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/x-javascript text/css application/xml;
    gzip_vary on;
    gzip_proxied expired no-cache no-store private auth;
    gzip_disable "MSIE [1-6]\.";

    server {
          listen         80;
          server_name     localhost;
          access_log      logs/access.log;
          server_name_in_redirect  off;
          location / {
                root  html;
                index index.html;
          }
    }

    include vhosts/*;
}

 这里只保留了一个本地的测试用例,其余的我们放在同目录下的vhosts下面,通过Nginx将vhosts下的文件全部加载进来作为配置。比如我们在vhosts下创建blog.useasp.net文件,里面保存blog.useasp.net网站的配置:

 server {
        listen       80;
        server_name  blog.useasp.net;

        charset utf-8;
        access_log  logs/blog.useasp.net.access.log;

        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

 这样配置后,访问blog.useasp.net的效果和直接在nginx.conf配置的效果一样,但却更容易维护,如果有更多的网站,只需要在vhosts文件夹下添加对应的配置文件即可,之后使用nginx -s reload重新加载配置文件。

关于博主

  一枚成分复杂的网络IT分子,属于互联网行业分类中的杂牌军。