Blog

centos7初装系统-ssh登录locale编码问题

勘误,之前这篇文章有错误    http://www.01happy.com/p3204/
问题不是系统自身编码问题,是不同系统的local登录衔接问题。

locale问题起因

登录 centos7 系统时,命令行模式下会出现一个警告:

[bash]
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
[/bash]

这个不是由于系统默认编码问题导致的,这个是因为两台电脑连接时,本地编码不能协调导致的,分析如下:

centos本机登录(没报错)

[root@localhost ~]# locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
[root@localhost ~]#

mac本机登录(没报错)

mbpdeMacBook-Pro:~ cool$ locale
LANG=
LC_COLLATE="C"
LC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
mbpdeMacBook-Pro:~ cool$

mac连接centos登录(报错了)

[root@localhost ~]# locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=en_US.UTF-8
LC_CTYPE=UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
[root@localhost ~]# 

locale背景知识

locale基本含义

locale就是某一个地域内的人们的语言习惯和文化传统和生活习惯。一个地区的locale就是根据这几大类的习惯定义的,这些locale定 义文件放在/usr/share/i18n/locales目录下面,例如en_US, zh_CN and de_DE@euro都是locale的定义文件,这些文件都是用文本格式书写的,你可以用写字板打开,看看里边的内容,当然出了有限的注释以外,大部分 东西可能你都看不懂,因为是用的Unicode的字符索引方式。

cat /usr/share/i18n/locales/zh_CN
comment_char %
escape_char  /
%
% Chinese language locale for the Peoples Republic of China
%
% This work is based on ISO PDTR 14652, Unicode 3.0, locale definition
% file for zh_CN revision 1.0 ([email protected], 1999-04-28) and
% charmap file for GBK version 1.0 ([email protected]).
%
% The file is designed to work with multiple charsets.  To ease the
% maintance and adding support for new charsets, all characters are
% in UCS notation and presented in Unicode order.
%
% Changelog:
% Tue Jul 25 2000 Yong Li <[email protected]>
% - first version for glibc 2.2

。。。。。。
。。。

locale内容说明

[oracle@game ~]$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8
[oracle@game ~]$ 

locale把按照所涉及到的文化传统的各个方面分成12个大类,这12个大类分别是: 

1、语言符号及其分类(LC_CTYPE) 
2、数字(LC_NUMERIC) 
3、比较和排序习惯(LC_COLLATE) 
4、时间显示格式(LC_TIME) 
5、货币单位(LC_MONETARY) 
6、信息主要是提示信息,错误信息,状态信息,标题,标签,按钮和菜单等(LC_MESSAGES) 
7、姓名书写方式(LC_NAME) 
8、地址书写方式(LC_ADDRESS) 
9、电话号码书写方式(LC_TELEPHONE) 
10、度量衡表达方式 (LC_MEASUREMENT) 
11、默认纸张尺寸大小(LC_PAPER) 
12、对locale自身包含信息的概述(LC_IDENTIFICATION)。

locale格式说明

zh_CN.GB2312到底是在说什么?

Locale是软件在运行时的语言环境, 它包括语言(Language), 地域 (Territory) 和字符集(Codeset)。

一个locale的书写格式为: 语言[_地域[.字符集]]。所以说呢,locale总是和一定的字符集相联系的。

下面举几个例子:

1、我说中文,身处中华人民共和国,使用国标2312字符集来表达字符。zh_CN.GB2312=中文_中华人民共和国+国标2312字符集。

2、我说中文,身处中华人民共和国,使用国标18030字符集来表达字符。zh_CN.GB18030=中文_中华人民共和国+国标18030字符集。

3、我说中文,身处中华人民共和国台湾省,使用国标Big5字符集来表达字符。zh_TW.BIG5=中文_台湾.大五码字符集

4、我说英文,身处大不列颠,使用ISO-8859-1字符集来表达字符。 en_GB.ISO-8859-1=英文_大不列颠.ISO-8859-1字符集

5、我说德语,身处德国,使用UTF-8字符集,习惯了欧洲风格。de_DE.UTF-8@euro=德语_德国.UTF-8字符集@按照欧洲习惯加以修正,注意不是[email protected],所以完全的locale表达方式是 [语言[_地域][.字符集] [@修正值]。

对于de_DE@euro的一点说明,@后边是修正项,也就是说你可以看到两个德国的locale:/usr/share/i18n/locales /de_DE@euro和/usr/share/i18n/locales/de_DE。

打开这两个locale定义,你就会知道它们的差别在于 de_DE@euro使用的是欧洲的排序、比较和缩进习惯,而de_DE用的是德国的标准习惯。

locale优先级说明

设定locale就是设定12大类的locale分类属性,即12个LC_*。除了这12个变量可以设定以外,为了简便起见,还有两个变量:LC_ALL和LANG。它们之间有一个优先级的关系:LC_ALL > LC_* >LANG可以这么说,LC_ALL是最上级设定或者强制设定,而LANG是默认设定值。

1、如果你设定了LC_ALL=zh_CN.UTF-8,那么不管LC_*和LANG设定成什么值,它们都会被强制服从LC_ALL的设定,成为 zh_CN.UTF-8。

2、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*=en_US.UTF-8,并且没有设定LC_ALL的话,那么系统的locale设定以LC_*=en_US.UTF-8。

3、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*,和LC_ALL均未设定的话,系统会将LC_*设定成默认值,也就是LANG的值zh_CN.UTF-8。

4、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_CTYPE=en_US.UTF-8,其他的LC_*,和LC_ALL均未设定的话, 那么系统的locale设定将是:LC_CTYPE=en_US.UTF-8,其余的 LC_COLLATE,LC_MESSAGES等等均会采用默认值,也就是 LANG的值,也就是LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=zh_CN.UTF-8。

所以,locale是这样设定的: 

1、如果你需要一个纯中文的系统的话,设定LC_ALL= zh_CN.XXXX,或者LANG=zh_CN.XXXX都可以,当然你可以两个都设定,但正如上面所讲,LC_ALL的值将覆盖所有其他的locale设定,不要作无用功。

2、如果你只想要一个可以输入中文的环境,而保持菜单、标题,系统信息等等为英文界面,那么只需要设定 LC_CTYPE=zh_CN.XXXX,LANG=en_US.XXXX就可以了这样LC_CTYPE=zh_CN.XXXX,而LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=en_US.XXXX。

3、假如你高兴的话,可以把12个LC_*一一设定成你需要的值,打造一个古灵精怪的系统: LC_CTYPE=zh_CN.GBK/GBK(使用中文编码内码GBK字符集); LC_NUMERIC=en_GB.ISO-8859-1(使用大不列颠的数字系统) [email protected](德国的度量衡使用ISO-8859-15字符集) 罗马的地址书写方式,美国的纸张设定……。估计没人这么干吧。

4、假如你什么也不做的话,也就是LC_ALL,LANG和LC_*均不指定特定值的话,系统将采用POSIX作为lcoale,也就是 C  locale。

也就是说如果没有设置这些环境变量的时候,在系统安装好的时候这些环境变量是有默认值的,默认值是POSIX。(这应该只针对英文系统,装中文系统的话,这些变量的默认值应该不是POSIX了。)
http://pubs.opengroup.org/onlinepubs/007908799/xbd/locale.html
http://pubs.opengroup.org/onlinepubs/007908799/xbd/locale.html#tag_005_002
这有Locale和POSIX locale的说明,有兴趣自己研究一下吧。

我的理解是,locale就相当于一个编码字符集,POSIX字符集里没有中文编码,所有如果使用POSIX编码的字符集去打开中文文件的话,就会出现乱码。

另外LANG和LANGUAGE有什么区别呢?

LANG – Specifies the default locale for all unset locale variables
LANGUAGE – Most programs use this for the language of its interface
LANGUAGE是应用程序中的设置语言的选项。而LANG是优先级很低的一个全局变量,它指定所有与locale有关的变量的默认值。

locale基本命令

### 查看系统默认的语言设置
[root@toy ~]# locale


### 查看所有语言
[root@room9pc01 ~]# locale -a
### 或者 查看系统支持的汉语区域语言
[root@toy ~]# localectl list-locales| grep zh 


### 查看当前区域配置
[root@toy ~]# localectl status
   System Locale: LANG=zh_CN.utf8
     VC Keymap: cn

     X11 Layout: cn


### 设置区域语言,其实在 /etc/locale.conf 在这个文本文件中,默认就一行 LANG=en_US.UTF-8
[root@toy ~]# localectl set-locale  LANG=zh_CN.utf8
### 查看上一条命令设置好的区域语言,
### 注意 centos6 是这个文件 /etc/sysconfig/i18n ,centos7 是 /etc/locale.conf
[root@toy ~]# cat /etc/locale.conf 
LANG=zh_CN.utf8 


### 刷新bash 或者重启,使设置生效 ###

locale问题分析

1、根据优先级:先找LC_ALL的配置,发现没有,就开始找 LC_CTYPE 。
2、然后 LC_CTYPE=UTF-8 ,在centos中找不到这个配置项,所以报错。

### 可以通过locale -a查看到系统支持的语系,
[root@localhost ~]# locale -a
aa_DJ
aa_DJ.iso88591
aa_DJ.utf8
aa_ER
aa_ER@saaho
aa_ER.utf8
aa_ER.utf8@saaho
aa_ET
。。。
。。
。

locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
这边两行的错误其实就是说LC_CTYPE这个编码文件找不到,然后LC_ALL也找不到。
3、因为前面两个都报错,所以默认就使用LANG的配置。

4、然后我们知道 /etc/sysconfig/i18n 和 /etc/sysconfig/i18n 中,都只设置了 LANG 变量,且系统连接时 LC_CTYPE 会将本机系统的值传递到远程主机的系统中。【LC_CTYPE  好像没有 设置过,应该是系统默认值】

locale问题解决方案

1、远程主机自己指定 LC_CTYPE 。在远程主机的本地化文件中添加  LC_CTYPE 的值,此优先级比客户端主机传递过来的值要高。

centos6下面全局语系的配置放在/etc/sysconfig/i18n文件,修改
$ vim /etc/sysconfig/i18n
增加   LC_CTYPE="en_US.UTF-8"
重启服务器,问题就解决了。


不过Centos7上没有/etc/sysconfig/i18n,
查了下有 /etc/locale.conf 文件起到同样的作用。
于是添加   LC_CTYPE="en_US.UTF-8"
重启服务器,问题就解决了。

2、取消客户端传递过来的 LC_CTYPE
在客户端编辑 vim /etc/ssh/ssh_config找到SendEnv LANG LC_*注释掉

3、修改客户端的  LC_CTYPE ,使得 LC_CTYPE= en_US.UTF-8,这样传递给远程主机时就能识别了。

4、在远程主机中,创建一个 UTF-8 的locale文件,这样子系统就能识别了,也就是可以找到该文件了。

举例:
编辑 /etc/locale.gen文件,反注释 en_US.UTF-8 UTF-8 一行.
执行生成命令  locale-gen
【locale-gen 好像在Ubuntu下可以,centos中没有这个命令】
http://manpages.ubuntu.com/manpages/bionic/man8/locale-gen.8.html

 

 


参考:

https://www.cloudbility.com/club/7195.html
https://www.jianshu.com/p/fb6c5d747700
https://www.jianshu.com/p/2b24861be987

https://blog.csdn.net/lemontree1945/article/details/80088986
https://www.cnblogs.com/xlmeng1988/archive/2013/01/16/locale.html

https://www.jianshu.com/p/2b24861be987

SSH-用screen恢复会话

你是不是经常需要 SSH 或者 telent 远程登录到 Linux 服务器?你是不是经常为一些长时间运行的任务而头疼,比如系统备份、ftp 传输等等。通常情况下我们都是为每一个这样的任务开一个远程终端窗口,因为他们执行的时间太长了。必须等待它执行完毕,在此期间可不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切半途而废了。

screen : 退出销毁操作

screen -ls 

There is a screen on:
    30339.pyapi (Detached)
1 Socket in /var/run/screen/S-root.

screen -r 30339        //进入要中断的screen

exit        //exit 或者 control +c 退出 screen

 

元凶:SIGHUP 信号

让我们来看看为什么关掉窗口/断开连接会使得正在运行的程序死掉。

在Linux/Unix中,有这样几个概念:

  • 进程组(process group):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID。
  • 会话期(session):一个或多个进程组的集合,有唯一一个会话期首进程(session leader)。会话期ID为首进程的ID。
  • 会话期可以有一个单独的控制终端(controlling terminal)。与控制终端连接的会话期首进程叫做控制进程(controlling process)。当前与终端交互的进程称为前台进程组。其余进程组称为后台进程组。

根据POSIX.1定义:

  • 挂断信号(SIGHUP)默认的动作是终止程序。
  • 当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。
  • 如果会话期首进程终止,则该信号发送到该会话期前台进程组。
  • 一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。

因此当网络断开或终端窗口关闭后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。

我们来看一个例子。打开两个SSH终端窗口,在其中一个运行top命令。

[root@tivf09 root]# top

在另一个终端窗口,找到top的进程ID为5180,其父进程ID为5128,即登录shell。

[root@tivf09 root]# ps -ef|grep top
root      5180  5128  0 01:03 pts/0    00:00:02 top
root      5857  3672  0 01:12 pts/2    00:00:00 grep top

使用pstree命令可以更清楚地看到这个关系:

[root@tivf09 root]# pstree -H 5180|grep top
|-sshd-+-sshd---bash---top

使用ps-xj命令可以看到,登录shell(PID 5128)和top在同一个会话期,shell为会话期首进程,所在进程组PGID为5128,top所在进程组PGID为5180,为前台进程组。

[root@tivf09 root]# ps -xj|grep 5128
 5126  5128  5128  5128 pts/0     5180 S        0   0:00 -bash
 5128  5180  5180  5128 pts/0     5180 S        0   0:50 top
 3672 18095 18094  3672 pts/2    18094 S        0   0:00 grep 5128

关闭第一个SSH窗口,在另一个窗口中可以看到top也被杀掉了。

[root@tivf09 root]# ps -ef|grep 5128
root     18699  3672  0 04:35 pts/2    00:00:00 grep 5128

如果我们可以忽略SIGHUP信号,关掉窗口应该就不会影响程序的运行了。nohup命令可以达到这个目的,如果程序的标准输出/标准错误是终端,nohup默认将其重定向到nohup.out文件。值得注意的是nohup命令只是使得程序忽略SIGHUP信号,还需要使用标记&把它放在后台运行。

nohup <command> [argument…] &

虽然nohup很容易使用,但还是比较“简陋”的,对于简单的命令能够应付过来,对于复杂的需要人机交互的任务就麻烦了。

其实我们可以使用一个更为强大的实用程序screen。流行的Linux发行版(例如Red Hat Enterprise Linux 4)通常会自带screen实用程序,如果没有的话,可以从GNU screen的官方网站下载。

[root@tivf06 ~]# rpm -qa|grep screen
xscreensaver-4.18-5.rhel4.11
screen-4.0.2-5

开始使用Screen

# 先在 服务器端 安装 screen
[root@ttsdy ~]# yum install screen

简单来说,Screen是一个可以在多个进程之间多路复用一个物理终端的窗口管理器。Screen中有会话的概念,用户可以在一个screen会话中创建多个screen窗口,在每一个screen窗口中就像操作一个真实的telnet/SSH连接窗口那样。在screen中创建一个新的窗口有这样几种方式:

1.直接在命令行键入screen命令

[bash]
[root@tivf06 ~]# screen
[/bash]

Screen将创建一个执行shell的全屏窗口。你可以执行任意shell程序,就像在ssh窗口中那样。在该窗口中键入exit退出该窗口,如果这是该screen会话的唯一窗口,该screen会话退出,否则screen自动切换到前一个窗口。

2.Screen命令后跟你要执行的程序。
[root@tivf06 ~]# screen vi test.c

Screen创建一个执行vi test.c的单窗口会话,退出vi将退出该窗口/会话。

3.以上两种方式都创建新的screen会话。我们还可以在一个已有screen会话中创建新的窗口。在当前screen窗口中键入C-a c,即Ctrl键+a键,之后再按下c键,screen 在该会话内生成一个新的窗口并切换到该窗口。

screen还有更高级的功能。你可以不中断screen窗口中程序的运行而暂时断开(detach)screen会话,并在随后时间重新连接(attach)该会话,重新控制各窗口中运行的程序。例如,我们打开一个screen窗口编辑/tmp/abc文件:

[root@tivf06 ~]# screen vi /tmp/abc

之后我们想暂时退出做点别的事情,比如出去散散步,那么在screen窗口键入C-a d,Screen会给出detached提示:

暂时中断会话

半个小时之后回来了,找到该screen会话:

[root@tivf06 ~]# screen -ls
There is a screen on:
        16582.pts-1.tivf06      (Detached)
1 Socket in /tmp/screens/S-root.

重新连接会话:

[root@tivf06 ~]# screen -r 16582

看看出现什么了,太棒了,一切都在。继续干吧。

你可能注意到给screen发送命令使用了特殊的键组合C-a。这是因为我们在键盘上键入的信息是直接发送给当前screen窗口,必须用其他方式向screen窗口管理器发出命令,默认情况下,screen接收以C-a开始的命令。这种命令形式在screen中叫做键绑定(key binding),C-a叫做命令字符(command character)。

可以通过C-a ?来查看所有的键绑定,常用的键绑定有:

Screen常用选项

使用键绑定C-a ?命令可以看到, 默认的命令字符(Command key)为C-a,转义C-a(literal ^a)的字符为a:

Screen 常用选项

因为screen把C-a看作是screen命令的开始,所以如果你想要screen窗口接收到C-a字符,就要输入C-a a。Screen也允许你使用-e选项设置自己的命令字符和转义字符,其格式为:

-exy x为命令字符,y为转义命令字符的字符

下面命令启动的screen会话指定了命令字符为C-t,转义C-t的字符为t,通过C-t ?命令可以看到该变化。

[root@tivf18 root]# screen -e^tt
自定义命令字符和转义字符

其他常用的命令选项有:

下例显示当前有两个处于detached状态的screen会话,你可以使用screen -r <screen_pid>重新连接上:

[root@tivf18 root]# screen –ls
There are screens on:
        8736.pts-1.tivf18       (Detached)
        8462.pts-0.tivf18       (Detached)
2 Sockets in /root/.screen.
 
[root@tivf18 root]# screen –r 8736

如果由于某种原因其中一个会话死掉了(例如人为杀掉该会话),这时screen -list会显示该会话为dead状态。使用screen -wipe命令清除该会话:

[root@tivf18 root]# kill -9 8462
[root@tivf18 root]# screen -ls  
There are screens on:
        8736.pts-1.tivf18       (Detached)
        8462.pts-0.tivf18       (Dead ???)
Remove dead screens with 'screen -wipe'.
2 Sockets in /root/.screen.
 
[root@tivf18 root]# screen -wipe
There are screens on:
        8736.pts-1.tivf18       (Detached)
        8462.pts-0.tivf18       (Removed)
1 socket wiped out.
1 Socket in /root/.screen.
 
[root@tivf18 root]# screen -ls  
There is a screen on:
        8736.pts-1.tivf18       (Detached)
1 Socket in /root/.screen.
 
[root@tivf18 root]#

-d –m 选项是一对很有意思的搭档。他们启动一个开始就处于断开模式的会话。你可以在随后需要的时候连接上该会话。有时候这是一个很有用的功能,比如我们可以使用它调试后台程序。该选项一个更常用的搭配是:-dmS sessionname

启动一个初始状态断开的screen会话:

[root@tivf06 tianq]# screen -dmS mygdb gdb execlp_test

连接该会话:

[root@tivf06 tianq]# screen -r mygdb

管理你的远程会话

先来看看如何使用screen解决SIGHUP问题,比如现在我们要ftp传输一个大文件。如果按老的办法,SSH登录到系统,直接ftp命令开始传输,之后。。如果网络速度还可以,恭喜你,不用等太长时间了;如果网络不好,老老实实等着吧,只能传输完毕再断开SSH连接了。让我们使用screen来试试。

SSH登录到系统,在命令行键入screen。

[root@tivf18 root]# screen

在screen shell窗口中输入ftp命令,登录,开始传输。不愿意等了?OK,在窗口中键入C-a d:

管理你的远程会话

然后。。退出SSH登录?随你怎样,只要别杀掉screen会话。

是不是很方便?更进一步,其实我们可以利用screen这种功能来管理你的远程会话,保存你所有的工作内容。你是不是每次登录到系统都要开很多窗口,然后每天都要重复打开关闭这些窗口?让screen来帮你“保存”吧,你只需要打开一个ssh窗口,创建需要的screen窗口,退出的时候C-a d“保存”你的工作,下次登录后直接screen -r <screen_pid>就可以了。

最好能给每个窗口起一个名字,这样好记些。使用C-a A给窗口起名字。使用C-a w可以看到这些窗口名字,可能名字出现的位置不同。使用putty:

putty

使用telnet:

telnet

更多Screen功能

Screen提供了丰富强大的定制功能。你可以在Screen的默认两级配置文件/etc/screenrc和$HOME/.screenrc中指定更多,例如设定screen选项,定制绑定键,设定screen会话自启动窗口,启用多用户模式,定制用户访问权限控制等等。如果你愿意的话,也可以自己指定screen配置文件。

以多用户功能为例,screen默认是以单用户模式运行的,你需要在配置文件中指定multiuser on 来打开多用户模式,通过acl*(acladd,acldel,aclchg...)命令,你可以灵活配置其他用户访问你的screen会话。更多配置文件内容请参考screen的man页。

参考资料

转载自:https://www.ibm.com/developerworks/cn/linux/l-cn-screen/

yum-Warning: RPMDB altered outside of yum

The warning means that you ran rpm directly instead of using yum.

Actually that was not required, the warning clears itself as soon as it appears. You only see it once, then yum internally checks the consistency and resets the warning so unless you then rerun rpm to install/uninstall something then you shouldn’t see the warning again.

bash-概述-脚本开头#!/bin/bash和#!/bin/sh的含义及区别

一直以为在shell脚本中#都是代表着注释功能,同样在脚本开始的#!/bin/sh也只是告诉用户这是一个shell脚本,而最近顺手查了下,才发现不是这个意思,分享下面的文章。

一、意思

#!/bin/sh是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面跟的是此解释此脚本的shell的路径。

$ cat /etc/shells可以查看系统支持的shell格式

其实第一句的#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的,我们可以用各种各样的解释器来写对应的脚本。

比如说/bin/csh脚本,/bin/perl脚本,/bin/awk脚本,/bin/sed脚本,甚至/bin/echo等等。

#!/bin/bash同理。

二、区别

Unix 系统是 Bourne Shell,Linux 系统是 Bourne Shell 的扩展即Bourne-Again Shell(bash)

GNU/Linux操作系统中的/bin/sh本是bash (Bourne-Again Shell) 的符号链接,但鉴于bash过于复杂,有人把bash从NetBSD移植到Linux并更名为dash (Debian Almquist Shell),并建议将/bin/sh指向它,以获得更快的脚本执行速度。Dash Shell 比Bash Shell小的多,符合POSIX标准。

所以也就是在Ubuntu中可以认为/bin/sh就是/bin/dash, 如果打算使用bash, 可直接将/bin/sh软链接到/bin/bash.

Ubuntu继承了Debian,所以从Ubuntu 6.10开始默认是Dash Shell。

应该说,/bin/sh/bin/bash虽然大体上没什么区别,但仍存在不同的标准。标记为#!/bin/sh的脚本不应使用任何POSIX没有规定的特性 (如let等命令, 但#!/bin/bash可以)。Debian曾经采用/bin/bash更改/bin/dash,目的使用更少的磁盘空间、提供较少的功能、获取更快的速度。但是后来经过shell脚本测试存在运行问题。因为原先在bash shell下可以运行的shell script (shell 脚本),在/bin/sh下还是会出现一些意想不到的问题,不是100%的兼用。

上面可以这样理解,使用man sh命令和man bash命令去观察,可以发现sh本身就是dash,也就更好的说明集成Debian系统之后的更改。

三、/bin/sh与/bin/bash的细微区别

在shell脚本的开头往往有一句话来定义使用哪种sh解释器来解释脚本。
目前研发送测的shell脚本中主要有以下两种方式:
(1) #!/bin/sh
(2) #!/bin/bash
在这里求教同福客栈的各位大侠们一个问题:
以上两种方式有什么区别?对于脚本的实际运行会产生什么不同的影响吗?

脚本test.sh内容:
#!/bin/sh
source pcy.sh #pcy.sh并不存在
echo hello
执行./test.sh,屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
由此可见,在#!/bin/sh的情况下,source不成功,不会运行source后面的代码。//前提sh未设成bash的软链接

修改test.sh脚本的第一行,变为#!/bin/bash,再次执行./test.sh,屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
hello
由此可见,在#!/bin/bash的情况下,虽然source不成功,但是还是运行了source后面的echo语句。

但是紧接着我又试着运行了一下sh ./test.sh,这次屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
表示虽然脚本中指定了#!/bin/bash,但是如果使用sh 方式运行,如果source不成功,也不会运行source后面的代码。

为什么会有这样的区别呢?

junru同学作了解释

1. sh一般设成bash的软链
[work@zjm-testing-app46 cy]$ ll /bin/sh
lrwxrwxrwx 1 root root 4 Nov 13 2006 /bin/sh -> bash
2. 在一般的linux系统当中(如redhat),使用sh调用执行脚本相当于打开了bash的POSIX标准模式
3. 也就是说 /bin/sh 相当于 /bin/bash –posix

所以,sh跟bash的区别,实际上就是bash有没有开启posix模式的区别

so,可以预想的是,如果第一行写成 #!/bin/bash –posix,那么脚本执行效果跟#!/bin/sh是一样的(遵循posix的特定规范,有可能就包括这样的规范:“当某行代码出错时,不继续往下解释”)

例如:
[root@localhost yuhj]# head -n1 x.sh
#!/bin/sh
[root@localhost yuhj]# ./x.sh

./x.sh: line 8: syntax error near unexpected token `<‘
./x.sh: line 8: ` while read line; do { echo $line;((Lines++)); } ; done < <(route -n)’
[root@localhost yuhj]#

 

[root@localhost yuhj]# head -n1 x.sh
#!/bin/bash
[root@localhost yuhj]#./x.sh

Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.202.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 192.168.202.2 0.0.0.0 UG 0 0 0 eth0
Number of lines read = 4
[root@localhost yuhj]#

[root@localhost yuhj]# head -n1 x.sh
#!/bin/bash –posix
[root@localhost yuhj]#
[root@localhost yuhj]# ./x.sh

./x.sh: line 8: syntax error near unexpected token `<‘
./x.sh: line 8: ` while read line; do { echo $line;((Lines++)); } ; done < <(route -n)’

 

[root@localhost yuhj]# whereis sh bash
sh: /bin/sh /usr/share/man/man1/sh.1.gz /usr/share/man/man1p/sh.1p.gz
bash: /bin/bash /usr/share/man/man1/bash.1.gz

[root@localhost yuhj]# ll /bin/sh /bin/bash
-rwxr-xr-x 1 root root 735004 May 25 2008 /bin/bash
lrwxrwxrwx 1 root root 4 Jan 29 00:39 /bin/sh -> bash

 

 

参考:

http://www.cnblogs.com/EasonJim/p/6850319.html
https://blog.csdn.net/MonMama/article/details/53390610

vim-入门基础

图片来自: http://www.cnblogs.com/zhangsf/archive/2013/06/13/3134409.html

公司新员工学习有用到,Vim官网的手册又太大而全,而网上各方资料要么不全面,要么不够基础。在网上搜集各方资料,按照自己的框架整理一份Vim入门基础教程,分享出来。特点是偏向基础,但对入门者来说足够全面,而且结构框架清晰。
另外,参考资料众多,没有一一标出来,如果作者看到,请联系我确认一下是否参考了你的资料,我会在文中标注出来。

1. 简介

Vim(Vi[Improved])编辑器是功能强大的跨平台文本文件编辑工具,继承自Unix系统的Vi编辑器,支持Linux/Mac OS X/Windows系统,利用它可以建立、修改文本文件。进入Vim编辑程序,可以在终端输入下面的命令:

$vim [filename]

其中filename是要编辑器的文件的路径名。如果文件不存在,它将为你建立一个新文件。Vim编辑程序有三种操作模式,分别称为 编辑模式插入模式 和 命令模式,当运行Vim时,首先进入编辑模式。

vim中显示行号命令   :set nu

2. 编辑模式

Vim编辑方式的主要用途是在被编辑的文件中移动光标的位置。一旦光标移到到所要的位置,就可以进行剪切和粘贴正文块,删除正文和插入新的正文。当完成所有的编辑工作后,需要保存编辑器结果,退出编辑程序回到终端,可以发出ZZ命令,连续按两次大写的Z键。

2.1 跳转

如果键盘上有上、下、左、右箭头的导航键,就由这些键来完成光标的移动。另外,可以用下面的键完成同样的 按字符移动 功能:

k               上移;
j               下移;
h               左移;
l               右移。

上面这4个键将光标位置每次移动一行或一个 字符 。Vim还提供稍大范围移动光标的命令:

ctrl+f      在文件中前移一页(相当于 page down);
ctrl+b      在文件中后移一页(相当于 page up);

更大范围的移动:

*         当光标停留在一个单词上,* 键会在文件内搜索该单词,并跳转到下一处;
#         当光标停留在一个单词上,# 在文件内搜索该单词,并跳转到上一处;
(/)     移动到 前/后 句 的开始;
{/}     跳转到 当前/下一个 段落 的开始。
g_      到本行最后一个不是 blank 字符的位置。
fa      到下一个为 a 的字符处,你也可以fs到下一个为s的字符。
t,      到逗号前的第一个字符。逗号可以变成其它字符。
3fa        在当前行查找第三个出现的 a。
F/T        和 f 和 t 一样,只不过是相反方向;
gg       将光标定位到文件第一行起始位置;
G         将光标定位到文件最后一行起始位置;
NG或Ngg  将光标定位到第 N 行的起始位置。

在屏幕中找到需要的 一页 时,可以用下面的命令快速移动光标:

H               将光标移到屏幕上的起始行(或最上行);
M               将光标移到屏幕中间;
L               将光标移到屏幕最后一行。

同样需要注意字母的大小写。H 和 L 命令还可以加数字。如 2H 表示将光标移到屏幕的第2行,3L 表示将光标移到屏幕的倒数第3行。
当将光标移到所要的行是,行内移动 光标可以用下面的命令来实现:

w               右移光标到下一个字的开头;
e               右移光标到一个字的末尾;
b               左移光标到前一个字的开头;
0               数字0,左移光标到本行的开始;
$               右移光标,到本行的末尾;
^               移动光标,到本行的第一个非空字符。

2.2 搜索匹配

和许多先进的编辑器一样,Vim 提供了强大的字符串搜索功能。要查找文件中指定字或短语出现的位置,可以用Vim直接进行搜索,而不必以手工方式进行。搜索方法是:键入字符 / ,后面跟以要搜索的字符串,然后按回车键。编辑程序执行正向搜索(即朝文件末尾方向),并在找到指定字符串后,将光标停到该字符串的开头;键入 n 命令可以继续执行搜索,找出这一字符串下次出现的位置。用字符 ? 取代 / ,可以实现反向搜索(朝文件开头方向)。例如:

/str1               正向搜索字符串 str1;
n                   继续搜索,找出 str1 字符串下次出现的位置;
N                   继续搜索,找出 str1 字符串上一次出现的位置;
?str2               反向搜索字符串 str2 。

无论搜索方向如何,当到达文件末尾或开头时,搜索工作会循环到文件的另一端并继续执行。
Vim中执行搜索匹配最强大的地方是结合 正则表达式 来搜索,后续将会介绍。

2.3 替换和删除

Vim常规的删除命令是 d、 x (前者删除  ,后者删除 字符 ),结合Vim的其他特性可以实现基础的删除功能。将光标定位于文件内指定位置后,可以用其他字符来替换光标所指向的字符,或从当前光标位置删除一个或多个字符或一行、多行。例如:

rc               用 c 替换光标所指向的当前字符;
nrc             用 c 替换光标所指向的前 n 个字符;
5rA             用 A 替换光标所指向的前 5 个字符;
x                 删除光标所指向的当前字符;
nx               删除光标所指向的前 n 个字符;
3x               删除光标所指向的前 3 个字符;
dw               删除光标右侧的字;
ndw             删除光标右侧的 n 个字;
3dw             删除光标右侧的 3 个字;
db               删除光标左侧的字;
ndb             删除光标左侧的 n 个字;
5db             删除光标左侧的 5 个字;
dd               删除光标所在行,并去除空隙;
ndd             删除(剪切) n 行内容,并去除空隙;
3dd             删除(剪切) 3 行内容,并去除空隙;

其他常用的删除命令有:

d$              从当前光标起删除字符直到行的结束;
d0              从当前光标起删除字符直到行的开始;
J                删除本行的回车符(CR),并和下一行合并。

 

Vim常规的替换命令有 c 和 s ,结合Vim的其他特性可以实现基础的替换功能,不过替换命令执行以后,通常会由 编辑模式 进入 插入模式 :

s               用输入的正文替换光标所指向的字符;
S               删除当前行,并进入插入模式;
ns               用输入的正文替换光标右侧 n 个字符;
nS             删除当前行在内的 n 行,并进入插入模式;
cw             用输入的正文替换光标右侧的字;
cW             用输入的正文替换从光标到行尾的所有字符(同 c$ );
ncw           用输入的正文替换光标右侧的 n 个字;
cb             用输入的正文替换光标左侧的字;
ncb              用输入的正文替换光标左侧的 n 个字;
cd               用输入的正文替换光标的所在行;
ncd              用输入的正文替换光标下面的 n 行;
c$               用输入的正文替换从光标开始到本行末尾的所有字符;
c0               用输入的正文替换从本行开头到光标的所有字符。

2.4 复制粘贴

从正文中删除的内容(如字符、字或行)并没有真正丢失,而是被剪切并复制到了一个内存缓冲区中。用户可将其粘贴到正文中的指定位置。完成这一操作的命令是:

p               小写字母 p,将缓冲区的内容粘贴到光标的后面;
P               大写字母 P,将缓冲区的内容粘贴到光标的前面。

如果缓冲区的内容是字符或字,直接粘贴在光标的前面或后面;如果缓冲区的内容为整行正文,执行上述粘贴命令将会粘贴在当前光标所在行的上一行或下一行。
注意上述两个命令中字母的大小写。Vim 编辑器经常以一对大、小写字母(如 p 和 P)来提供一对相似的功能。通常,小写命令在光标的后面进行操作,大写命令在光标的前面进行操作。

有时需要复制一段正文到新位置,同时保留原有位置的内容。这种情况下,首先应当把指定内容复制(而不是剪切)到内存缓冲区。完成这一操作的命令是:

yy              复制当前行到内存缓冲区;
nyy             复制 n 行内容到内存缓冲区;
5yy             复制 5 行内容到内存缓冲区;
“+y          复制 1 行到操作系统的粘贴板;
“+nyy          复制 n 行到操作系统的粘贴板。

2.5 撤销和重复

在编辑文档的过程中,为消除某个错误的编辑命令造成的后果,可以用撤消命令。另外,如果用户希望在新的光标位置重复前面执行过的编辑命令,可用重复命令。

u               撤消前一条命令的结果;
.              重复最后一条修改正文的命令。

3. 插入模式

3.1 进入插入模式

在编辑模式下正确定位光标之后,可用以下命令切换到插入模式:

i           在光标左侧插入正文
a            在光标右侧插入正文
o            在光标所在行的下一行增添新行
O           在光标所在行的上一行增添新行
I            在光标所在行的开头插入
A           在光标所在行的末尾插入

3.2 退出插入模式

退出插入模式的方法是,按 ESC 键或组合键 Ctrl+[ ,退出插入模式之后,将会进入编辑模式 。

4. 命令模式

在Vim的命令模式下,可以使用复杂的命令。在编辑模式下键入 : ,光标就跳到屏幕最后一行,并在那里显示冒号,此时已进入命令模式。命令模式又称 末行模式 ,用户输入的内容均显示在屏幕的最后一行,按回车键,Vim 执行命令。

4.1 打开、保存、退出

在已经启动的Vim中打开一个文件需要用 :e 命令:

:e path_to_file/filename

保存当前编辑的文件需要用 :w 命令(单词 write 的缩写):

:w

将当前文件另存为 file_temp 则:

:w file_temp

在编辑模式下可以用 ZZ 命令退出Vim编辑程序,该命令保存对正文所作的修改,覆盖原始文件。如果只需要退出编辑程序,而不打算保存编辑的内容,可用下面的命令:

: q             在未作修改的情况下退出;
: q!               放弃所有修改,退出编辑程序。

保存并退出则可以讲两条命令结合起来使用(注意命令顺序,先保存,后退出):

:wq

4.2 行号与文件

编辑中的每一行正文都有自己的行号,用下列命令可以移动光标到指定行(效果与 编辑模式 下的 ngg 或 nG 相同):

: n             将光标移到第 n 行

命令模式下,可以规定命令操作的行号范围。数值用来指定绝对行号;字符“.”表示光标所在行的行号;字符符“$”表示正文最后一行的行号;简单的表达式,例如“.+5”表示当前行往下的第 5 行。例如:

:345                  将光标移到第 345 行
:345w file          将第 345 行写入 file 文件
:3,5w file          将第 3 行至第 5 行写入 file 文件
:1,.w file          将第 1 行至当前行写入 file 文件
:.,$w file          将当前行至最后一行写入 file 文件
:.,.+5w file          从当前行开始将 6 行内容写入 file 文件
:1,$w file          将所有内容写入 file 文件,相当于 :w file 命令

在命令模式下,允许从文件中读取正文,或将正文写入文件。例如:

:w                 将编辑的内容写入原始文件,用来保存编辑的中间结果
:wq             将编辑的内容写入原始文件并退出编辑程序(相当于 ZZ 命令)
:w file         将编辑的内容写入 file 文件,保持原有文件的内容不变
:a,bw file       将第 a 行至第 b 行的内容写入 file 文件
:r file         读取 file 文件的内容,插入当前光标所在行的后面
:e file         编辑新文件 file 代替原有内容
:f file         将当前文件重命名为 file
:f               打印当前文件名称和状态,如文件的行数、光标所在的行号等

4.3 字符串搜索

在 编辑模式 讲过字符串的搜索,此处的 命令模式 也可以进行字符串搜索,给出一个字符串,可以通过搜索该字符串到达指定行。如果希望进行正向搜索,将待搜索的字符串置于两个 / 之间;如果希望反向搜索,则将字符串放在两个 ? 之间。例如:

:/str/                正向搜索,将光标移到下一个包含字符串 str 的行
:?str?                反向搜索,将光标移到上一个包含字符串 str 的行
:/str/w file            正向搜索,并将第一个包含字符串 str 的行写入 file 文件
:/str1/,/str2/w file    正向搜索,并将包含字符串 str1 的行至包含字符串 str2 的行写

4.4 Vim中的正则表达式

当给Vim指定搜索字符串时,可以包含具有特殊含义的字符。包含这些特殊字符的搜索字符串称为正则表达式(Regular Expressions)。例如,要搜索一行正文,这行正文的开头包含 struct 字。下面的命令做不到这一点:

:/struct/

因为它只找出在行中任意位置包含 struct的第一行,并不一定在行的开始包含 struct。解决问题的办法是在搜索字符串前面加上特殊字符^:

:/^struct/

^ 字符比较每行开头的字符串。所以上面的命令表示:找出以字符串 struct 开头的行。
也可以用类似办法在搜索字符串后面加上表示行的末尾的特殊字符 $ 来找出位于行末尾的字:

:/^struct/

下表给出大多数特殊字符和它们的含义:

^               放在字符串前面,匹配行首的字;
$               放在字符串后面,匹配行尾的字;
\<             匹配一个字的字头;
\>             匹配一个字的字尾;
.               匹配任何单个正文字符;
[str]           匹配 str 中的任何单个字符;
[^str]         匹配任何不在 str 中的单个字符;
[a-b]           匹配 a 到 b 之间的任一字符;
*               匹配前一个字符的 0 次或多次出现;
\               转义后面的字符。

简单介绍这么多,正则表达式知识可以参考
《正则表达式30分钟入门》:http://deerchao.net/tutorials/regex/regex.htm
另外,进阶的Vim正则表达式还有对Magic 模式的介绍,可以参考
《Vim正则表达式详解》:
http://blog.csdn.net/salc3k/article/details/8222397

4.5 正文替换

利用 :s 命令可以实现字符串的替换。具体的用法包括:

:%s/str1/str2/      用字符串 str2 替换行中首次出现的字符串 str1
:s/str1/str2/g      用字符串 str2 替换行中所有出现的字符串 str1
:.,$ s/str1/str2/g  用字符串 str2 替换正文当前行到末尾所有出现的字符串 str1
:1,$ s/str1/str2/g  用字符串 str2 替换正文中所有出现的字符串 str1
:g/str1/s//str2/g    功能同上
:m,ns/str1/str2/g    将从m行到n行的str1替换成str2

从上述替换命令可以看到:

  1. `g` 放在命令末尾,表示对搜索字符串的每次出现进行替换,不止匹配每行中的第一次出现;不加 `g`,表示只对搜索字符串的首次出现进行替换;`g` 放在命令开头,表示对正文中所有包含搜索字符串的行进行替换操作;
  2. `s` 表示后面跟着一串替换的命令;
  3. `%` 表示替换范围是所有行,即全文。

另外一个实用的命令,在Vim中统计当前文件中字符串 str1 出现的次数,可用替换命令的变形:

:%s/str1/&/gn

4.6 删除正文

在命令模式下,同样可以删除正文中的内容。例如:

:d                            删除光标所在行
:3d                          删除 3 行
:.,$d                          删除当前行至正文的末尾
:/str1/,/str2/d              删除从字符串 str1 到 str2 的所有行
:g/^\(.*\)$\n\1$/d              删除连续相同的行,保留最后一行
:g/\%(^\1$\n\)\@<=\(.*\)$/d     删除连续相同的行,保留最开始一行
:g/^\s*$\n\s*$/d                删除连续多个空行,只保留一行空行
:5,20s/^#//g                    删除5到20行开头的 # 注释

总之,Vim的初级删除命令是用 d ,高级删除命令可以用 正则替换 的方式执行。

4.7 恢复文件

Vim 在编辑某个文件时,会另外生成一个临时文件,这个文件的名称通常以 . 开头,并以 .swp 结尾。Vim 在正常退出时,该文件被删除,若意外退出,而没有保存文件的最新修改内容,则可以使用恢复命令 :recover 来恢复文件,也可以在启动Vim时用 -r 选项。

4.8 选项设置

为控制不同的编辑功能,Vim 提供了很多内部选项。利用 :set 命令可以设置选项。基本语法为:

:set option         设置选项 option

常见的功能选项包括:

autoindent      设置该选项,则正文自动缩进
ignorecase      设置该选项,则忽略规则表达式中大小写字母的区别
number          设置该选项,则显示正文行号
ruler           设置该选项,则在屏幕底部显示光标所在行、列的位置
tabstop         设置按 Tab 键跳过的空格数。例如 :set tabstop=n,n 默认值为 8
mk              将选项保存在当前目录的 .exrc 文件中

4.9 Shell切换

当处于编辑的对话过程中时,可能需要执行一些Linux命令。如果需要保存当前的结果,退出编辑程序,再执行所需的Linux命令,然后再回头继续编辑过程,就显得十分累赘。如果能在编辑的环境中运行Linux命令就要省事得多。在Vim中,可以用下面的命令来做到这一点:

:!shell_command   执行完 shell_command 后回到Vim

这称为Shell切换。它允许执行任何可以在标准的Shell提示符下执行的命令。当这条命令执行完毕,控制返回给编辑程序。又可以继续编辑对话过程。

4.10 分屏与标签页

分屏

普通的Vim模式,打开一个Vim程序只能查看一个文件,如果想同时查看多个文件,就需要用到Vim分屏与标签页功能。
Vim的分屏,主要有两种方式:上下分屏(水平分屏)和左右分屏(垂直分屏),在命令模式分别敲入以下命令即可:

:split(可用缩写 :sp)            上下分屏;
:vsplit(可用缩写 :vsp)        左右分屏。

另外,也可以在终端里启动vim时就开启分屏操作:

vim -On file1 file2...   打开 file1 和 file2 ,垂直分屏
vim -on file1 file2...   打开 file1 和 file2 ,水平分屏

理论上,一个Vim窗口,可以分为多个Vim屏幕,切换屏幕需要用键盘快捷键,命令分别有:

Ctrl+w+h            切换到当前分屏的左边一屏;
Ctrl+w+l            切换到当前分屏的右边一屏;
Ctrl+w+j            切换到当前分屏的下方一屏;
Ctrl+w+k            切换到当前分屏的上方一屏。

即键盘上的h,j,k,l 四个Vim专用方向键,配合Ctrl键和w键(window的缩写),就能跳转到目标分屏。另外,也可以直接按 Ctrl+w+w 来跳转分屏,不过跳转方向则是在当前Vim窗口所有分屏中,按照逆时针方向跳转。
下面是改变尺寸的一些操作,主要是高度,对于宽度你可以使用 [Ctrl+W <] 或是 [Ctrl+W >] ,但这可能需要最新的版本才支持。

Ctrl+W =            让所有的屏都有一样的高度;
Ctrl+W +            增加高度;
Ctrl+W -            减少高度。

标签页

Vim的标签(Tab)页,类似浏览器的标签页,一个标签页打开一个Vim的窗口,一个Vim的窗口可以支持N个分屏。
在Vim中新建一个标签的命令是:

:tabnew

如果要在新建标签页的同时打开一个文件,则可以在命令后面直接附带文件路径:

:tabnew filename

Vim中的每个标签页有一个唯一的数字序号,第一个标签页的序号是0,从左向右依次加一。关于标签页有一系列操作命令,简介如下:

:tN[ext]                跳转到上一个匹配的标签
:tabN[ext]              跳到上一个标签页
:tabc[lose]             关闭当前标签页
:tabdo                  为每个标签页执行命令
:tabe[dit]              在新标签页里编辑文件
:tabf[ind]              寻找 'path' 里的文件,在新标签页里编辑之
:tabfir[st]             转到第一个标签页
:tabl[ast]              转到最后一个标签页
:tabm[ove]  N           把标签页移到序号为N位置
:tabnew [filename]      在新标签页里编辑文件
:tabn[ext]              转到下一个标签页
:tabo[nly]              关闭所有除了当前标签页以外的所有标签页
:tabp[revious]          转到前一个标签页
:tabr[ewind]            转到第一个标签页

4.11 与外部工具集成

Vim可以与许多外部程序集成,功能十分强大,比如 diff , ctags , sort , xxd 等等,下面选取几个简单介绍一下。

diff

Linux命令 diff 用来对比两个文件的内容,不过对比结果显示在终端里,可读性比较差。结合Vim,在终端里可以直接输入命令 vimdiff,后面跟两个文件名作为参数:

vimdiff file1 file2

即可在Vim里分屏显示两个文件内容的对比结果,对文件内容差异部分进行高亮标记,还可以同步滚动两个文件内容,更可以实时修改文件内容,方便程度和用户体验大大提高。

vimdiff a.txt b.txt

如果直接给 -d 选项是一样的

vim -d a.txt b.txt

除了在终端里开启vimdiff 功能,也可以在打开Vim后,在Vim的命令模式输入相关命令来开启 vimdiff 功能:

:diffsplit abc.txt

如果你现在已经开启了一个文件,想Vim帮你区分你的文件跟 abc.txt 有什么区别,可以在Vim中用 diffsplit 的方式打开第二个文件,这个时 候Vim会用 split(分上下两屏)的方式开启第二个文件,并且通过颜色,fold来显示两个文件的区别
这样Vim就会用颜色帮你区分开2个文件的区别。如果文件比较大(源码)重复的部分会帮你折叠起来。

:diffpatch filename

通过 :diffpatch 你的patch的文件名,就可以以当前文件加上你的patch来显示。vim会split一个新的屏,显示patch后的信息并且用颜色标明区别。
如果不喜欢上下对比,喜欢左右(比较符合视觉)可以在前面加 vert ,例如:

:vert diffsplit abc.txt
:vert diffpatch abc.txt

看完diff,用 :only 回到原本编辑的文件,觉得diff的讨厌颜色还是在哪里,只要用 :diffoff 关闭就好了。
还有个常用的diff中的就是 :diffu ,这个是 :diffupdate 的简写,更新的时候用。
Vim的diff功能显示效果如下所示:

 

图片来自 http://www.2cto.com/net/201608/536924.html

sort

Linux命令 sort 可以对文本内容进行按行中的字符比较、排序,但在终端里使用 sort命令处理文件,并不能实时查看文件内容。具体用法请自查手册。

xxd

vim+xxd 是Linux下最常用的二进制文本编辑工具,xxd其实是Vim外部的一个转换程序,随Vim一起发布,在Vim里调用它来编辑二进制文本非常方便。
首先以二进制模式在终端里打开一个文件:

vim -b filename

Vim 的 -b 选项是告诉 Vim 打开的是一个二进制文件,不指定的话,会在后面加上 0x0a ,即一个换行符。
然后在Vim的命令模式下键入:

:%!xxd

即可看到二进制模式显示出来的文本,看起来像这样:

0000000: 1f8b 0808 39d7 173b 0203 7474 002b 4e49  ....9..;..tt.+NI 
0000010: 4b2c 8660 eb9c ecac c462 eb94 345e 2e30  K,......b..4^.0 
0000020: 373b 2731 0b22 0ca6 c1a2 d669 1035 39d9  7;'1.".....i.59

然后就可以在二进制模式下编辑该文件,编辑后保存,然后用下面命令从二进制模式转换到普通模式:

:%!xxd -r

另外,也可以调整二进制的显示模式,默认是 2 个字节为一组,可以通过 g 参数调整每组字节数:

:%!xxd -g 1         表示每1个字节为1组 
:%!xxd -g 2         表示每2个字节为1组(默认) 
:%!xxd -g 4         表示每4个字节为1组

5. Vim配置

最初安装的Vim功能、特性支持比较少,用起来比较费劲,想要稍微“好用”一点,需做一些初步的配置。Vim的配置主要分为Vim本身特性的配置和外部插件的配置两部分。
Vim的配置是通常是存放在用户主目录的 .vimrc 的隐藏文件中的。就Vim本身特性来说,基础的配置有编程语言语法高亮、缩进设置、行号显示、搜索高亮、TAB键设置、字体设置、Vim主题设置等等,稍微高级一些的有编程语言缩进、自动补全设置等,具体配置项可以自行查资料,全面详细的配置项介绍可以参考:
《Vim Options》:
http://vimcdoc.sourceforge.net/doc/options.html#%27completeopt%27

6. Vim插件

Vim“编辑器之神”的称号并不是浪得虚名,然而,这个荣誉的背后,或许近半的功劳要归功于强大的插件支持特性,以及社区开发的各种各样功能强大的插件。

平时开发人员常用插件主要是目录(文件)查看和管理、编程语言缩进与自动补全、编程语言Docs支持、函数跳转、项目管理等等,简单配置可以参考下面:

《Vim插件简单介绍》:
http://blog.segmentfault.com/xuelang/1190000000630547

《手把手教你把Vim改装成一个IDE编程环境(图文)》:
http://blog.csdn.net/wooin/article/details/1858917

《将Vim改造为强大的IDE》:
http://www.cnblogs.com/zhangsf/archive/2013/06/13/3134409.html

当然,这些插件都是拜Vim本身的插件支持特性所赐。Vim为了支持丰富的第三方插件,自身定义了一套简单的脚本开发语言,供程序员自行开发自己所需要的插件,插件开发介绍可以参考:

《Writing Vim Plugins》:
http://stevelosh.com/blog/2011/09/writing-vim-plugins/

7. Vim完整文档

  1. Vim官方文档:http://vimdoc.sourceforge.net/
  2. Vim中文用户手册7_3.pdf :http://pan.baidu.com/s/1jGzbTBo

请问有时会看到诸如 <C-x> 这样的快捷键,这是什么意思,要怎么按出来呢?
按: Ctrl+C

转载自:  https://www.jianshu.com/p/bcbe916f97e1

96
甲鱼 

vim-常用命令不断更新

VIM 简单入门

一、安装 Vim;
二、在命令行中输入 vimtutor 或者 gvimtutor 并阅读;
三、开始日常使用,在遇到问题时使用 :help 命令。
喜欢看中文文档者增加一步: 搜索 vimcdoc ,然后下载并安装中文文档。

VIM 常用命令不断更新

1、用vim打开文件   
vi  文件路径

2、按字母 i 进入 编辑模式;

3、按 :wq 或者 按 :x 保存退出

":x"和":wq"的真正区别,如下:
:wq 强制性写入文件并退出。即使文件没有被修改也强制写入,并更新文件的修改时间。
:x 写入文件并退出。仅当文件被修改时才写入,并更新文件修改时间,否则不会更新文件修改时间。

编译代码时,在没有修改源文件的情况下,仅仅使用":wq"命令保存文件,源文件会重新编译。
这是因为文件即使没有修改,":wq"强制更新文件的修改时间,
这样会让 make编译整个项目时以为文件被修改过了,然后就得重新编译链接生成可执行文件。

坑爹生活反思-复制文章时编辑器模式选择

最初在网上 看到一篇 不错的文章想复制下来时,我都是 通过 visual 模式 编辑文章的,一开始觉得 理所应当。感觉效果还不错,很方便。后来我 通过 这种方式 ,又 复制了 一遍 很多 代码的文章。

但是 代码多的 文章,我觉得代码 不好看的,于是 就 开始 改样式了,删了很多 div 和 html。
于是 这个时间花的 比较多了,我觉的 还是 直接 将 复制的 文本 ,粘贴 到 text 编辑模式 更好。
可以 直接 编辑 代码的 格式。

下次注意啦,做事情 需要 有远见,需要 能 预测 未来 !

到最后,权衡利弊来看,最佳的做法是,切片任务。
一部分,一部分,复制文章。看这部分 适合 visual 模式 还是 text 模式。这样是 最省力的,下次注意啦。


今天又遇到一篇多图文章的技术贴,我决得还是,一边编辑,一边上传图片,效率最高了。

bash-网络-linux netstat命令详解

简介

Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等。

输出信息含义

执行netstat后,其输出结果为

Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 2 210.34.6.89:telnet 210.34.6.96:2873 ESTABLISHED
tcp 296 0 210.34.6.89:1165 210.34.6.84:netbios-ssn ESTABLISHED
tcp 0 0 localhost.localdom:9001 localhost.localdom:1162 ESTABLISHED
tcp 0 0 localhost.localdom:1162 localhost.localdom:9001 ESTABLISHED
tcp 0 80 210.34.6.89:1161 210.34.6.10:netbios-ssn CLOSE

Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags Type State I-Node Path
unix 1 [ ] STREAM CONNECTED 16178 @000000dd
unix 1 [ ] STREAM CONNECTED 16176 @000000dc
unix 9 [ ] DGRAM 5292 /dev/log
unix 1 [ ] STREAM CONNECTED 16182 @000000df

从整体上看,netstat的输出结果可以分为两个部分:

一个是Active Internet connections,称为有源TCP连接,其中”Recv-Q”和”Send-Q”指%0A的是接收队列和发送队列。这些数字一般都应该是0。如果不是则表示软件包正在队列中堆积。这种情况只能在非常少的情况见到。

另一个是Active UNIX domain sockets,称为有源Unix域套接口(和网络套接字一样,但是只能用于本机通信,性能可以提高一倍)。
Proto显示连接使用的协议,RefCnt表示连接到本套接口上的进程号,Types显示套接口的类型,State显示套接口当前的状态,Path表示连接到套接口的其它进程使用的路径名。

常见参数

-a (all)显示所有选项,默认不显示LISTEN相关
-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化成数字。
-l 仅列出有在 Listen (监听) 的服務状态

-p 显示建立相关链接的程序名
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c 每隔一个固定时间,执行该netstat命令。

提示:LISTEN和LISTENING的状态只有用-a或者-l才能看到

 

实用命令实例

 

1. 列出所有端口 (包括监听和未监听的)

  列出所有端口 netstat -a

# netstat -a | more
 Active Internet connections (servers and established)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State
 tcp        0      0 localhost:30037         *:*                     LISTEN
 udp        0      0 *:bootpc                *:*
 
Active UNIX domain sockets (servers and established)
 Proto RefCnt Flags       Type       State         I-Node   Path
 unix  2      [ ACC ]     STREAM     LISTENING     6135     /tmp/.X11-unix/X0
 unix  2      [ ACC ]     STREAM     LISTENING     5140     /var/run/acpid.socket

  列出所有 tcp 端口 netstat -at

# netstat -at
 Active Internet connections (servers and established)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State
 tcp        0      0 localhost:30037         *:*                     LISTEN
 tcp        0      0 localhost:ipp           *:*                     LISTEN
 tcp        0      0 *:smtp                  *:*                     LISTEN
 tcp6       0      0 localhost:ipp           [::]:*                  LISTEN

  列出所有 udp 端口 netstat -au

# netstat -au
 Active Internet connections (servers and established)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State
 udp        0      0 *:bootpc                *:*
 udp        0      0 *:49119                 *:*
 udp        0      0 *:mdns                  *:*

2. 列出所有处于监听状态的 Sockets

  只显示监听端口 netstat -l

# netstat -l
 Active Internet connections (only servers)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State
 tcp        0      0 localhost:ipp           *:*                     LISTEN
 tcp6       0      0 localhost:ipp           [::]:*                  LISTEN
 udp        0      0 *:49119                 *:*

  只列出所有监听 tcp 端口 netstat -lt

# netstat -lt
 Active Internet connections (only servers)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State
 tcp        0      0 localhost:30037         *:*                     LISTEN
 tcp        0      0 *:smtp                  *:*                     LISTEN
 tcp6       0      0 localhost:ipp           [::]:*                  LISTEN

  只列出所有监听 udp 端口 netstat -lu

# netstat -lu
 Active Internet connections (only servers)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State
 udp        0      0 *:49119                 *:*
 udp        0      0 *:mdns                  *:*

  只列出所有监听 UNIX 端口 netstat -lx

# netstat -lx
 Active UNIX domain sockets (only servers)
 Proto RefCnt Flags       Type       State         I-Node   Path
 unix  2      [ ACC ]     STREAM     LISTENING     6294     private/maildrop
 unix  2      [ ACC ]     STREAM     LISTENING     6203     public/cleanup
 unix  2      [ ACC ]     STREAM     LISTENING     6302     private/ifmail
 unix  2      [ ACC ]     STREAM     LISTENING     6306     private/bsmtp

3. 显示每个协议的统计信息

  显示所有端口的统计信息 netstat -s

# netstat -s
 Ip:
 11150 total packets received
 1 with invalid addresses
 0 forwarded
 0 incoming packets discarded
 11149 incoming packets delivered
 11635 requests sent out
 Icmp:
 0 ICMP messages received
 0 input ICMP message failed.
 Tcp:
 582 active connections openings
 2 failed connection attempts
 25 connection resets received
 Udp:
 1183 packets received
 4 packets to unknown port received.
 .....

  显示 TCP 或 UDP 端口的统计信息 netstat -st 或 -su

# netstat -st 
# netstat -su

4. 在 netstat 输出中显示 PID 和进程名称 netstat -p

netstat -p 可以与其它开关一起使用,就可以添加 “PID/进程名称” 到 netstat 输出中,这样 debugging 的时候可以很方便的发现特定端口运行的程序。

 # netstat -pt
 Active Internet connections (w/o servers)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
 tcp        1      0 ramesh-laptop.loc:47212 192.168.185.75:www        CLOSE_WAIT  2109/firefox
 tcp        0      0 ramesh-laptop.loc:52750 lax:www ESTABLISHED 2109/firefox

5. 在 netstat 输出中不显示主机,端口和用户名 (host, port or user)

当你不想让主机,端口和用户名显示,使用 netstat -n。将会使用数字代替那些名称。

同样可以加速输出,因为不用进行比对查询。

# netstat -an

如果只是不想让这三个名称中的一个被显示,使用以下命令

# netsat -a --numeric-ports
# netsat -a --numeric-hosts
# netsat -a --numeric-users

6. 持续输出 netstat 信息

netstat 将每隔一秒输出网络信息。

# netstat -c
 Active Internet connections (w/o servers)
 Proto Recv-Q Send-Q Local Address           Foreign Address         State
 tcp        0      0 ramesh-laptop.loc:36130 101-101-181-225.ama:www ESTABLISHED
 tcp        1      1 ramesh-laptop.loc:52564 101.11.169.230:www      CLOSING
 tcp        0      0 ramesh-laptop.loc:43758 server-101-101-43-2:www ESTABLISHED
 tcp        1      1 ramesh-laptop.loc:42367 101.101.34.101:www      CLOSING
 ^C

7. 显示系统不支持的地址族 (Address Families)

netstat --verbose

在输出的末尾,会有如下的信息

netstat: no support for `AF IPX' on this system.
netstat: no support for `AF AX25' on this system.
netstat: no support for `AF X25' on this system.
netstat: no support for `AF NETROM' on this system.

8. 显示核心路由信息 netstat -r

# netstat -r
 Kernel IP routing table
 Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
 192.168.1.0     *               255.255.255.0   U         0 0          0 eth2
 link-local      *               255.255.0.0     U         0 0          0 eth2
 default         192.168.1.1     0.0.0.0         UG        0 0          0 eth2

注意: 使用 netstat -rn 显示数字格式,不查询主机名称。

9. 找出程序运行的端口

并不是所有的进程都能找到,没有权限的会不显示,使用 root 权限查看所有的信息。

# netstat -ap | grep ssh
 tcp        1      0 dev-db:ssh           101.174.100.22:39213        CLOSE_WAIT  -
 tcp        1      0 dev-db:ssh           101.174.100.22:57643        CLOSE_WAIT  -

  找出运行在指定端口的进程

# netstat -an | grep ':80'

10. 显示网络接口列表

# netstat -i
 Kernel Interface table
 Iface   MTU Met   RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
 eth0       1500 0         0      0      0 0             0      0      0      0 BMU
 eth2       1500 0     26196      0      0 0         26883      6      0      0 BMRU
 lo        16436 0         4      0      0 0             4      0      0      0 LRU

显示详细信息,像是 ifconfig 使用 netstat -ie:

# netstat -ie
 Kernel Interface table
 eth0      Link encap:Ethernet  HWaddr 00:10:40:11:11:11
 UP BROADCAST MULTICAST  MTU:1500  Metric:1
 RX packets:0 errors:0 dropped:0 overruns:0 frame:0
 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000
 RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
 Memory:f6ae0000-f6b00000

11. IP和TCP分析

  查看连接某服务端口最多的的IP地址

wss8848@ubuntu:~$ netstat -nat | grep "192.168.1.15:22" |awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -20
18 221.136.168.36
3 154.74.45.242
2 78.173.31.236
2 62.183.207.98
2 192.168.1.14
2 182.48.111.215
2 124.193.219.34
2 119.145.41.2
2 114.255.41.30
1 75.102.11.99

  TCP各种状态列表

wss8848@ubuntu:~$ netstat -nat |awk '{print $6}'
established)
Foreign
LISTEN
TIME_WAIT
ESTABLISHED
TIME_WAIT
SYN_SENT

先把状态全都取出来,然后使用uniq -c统计,之后再进行排序。

wss8848@ubuntu:~$ netstat -nat |awk '{print $6}'|sort|uniq -c
143 ESTABLISHED
1 FIN_WAIT1
1 Foreign
1 LAST_ACK
36 LISTEN
6 SYN_SENT
113 TIME_WAIT
1 established)

最后的命令如下:

netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn

分析access.log获得访问前10位的ip地址

awk '{print $1}' access.log |sort|uniq -c|sort -nr|head -10

转载自:http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316661.html
顺便转载下主页:https://home.cnblogs.com/u/ggjucheng/