Anwen——Java技术博客,立志成为斜杠青年:IT极客/健身/旅行/国菜大厨

别人的看法都是狗屁,你是谁只有自己说了算。若命运不公,就和他斗到底。
——《哪吒之魔童降世》

目录
Linux问题汇总
/  

Linux问题汇总

# 环境

  • Windows10,64位,8G内存
  • VMware Workstation 12
  • CentOS-6.7-x86_64-bin-DVD1.iso

网络配置

NAT模式

NAT模式的特点是,虚拟机和宿主机组成一个独立的虚拟网络,而不受宿主机所在物理网络(外网)的影响。

如上图所示,虚拟机会虚拟出一个交换机,这个交换机的属性可以在VMware->编辑->虚拟网络编辑器中设置。一般路由器也即网关的IP的主机部分设置为1(IP中对应子网掩码为1的位为网络部分,用来区分网段;对应子网掩码为0的位为主机部分,用来区分该网段内的主机。如network为255.255.255.0时,其前24位位1,后8位位0,则IP192.168.25.1的网络部分为192.168.25而主机部分为1),这是约定俗成的。在设置好网关IP之后,我们就能得到网关的IP、子网掩码了。

1、配置网关

根据子网IP192.168.25.0以及网关的主机部分约定俗成为1,我们将NAT设置中的网关IP设置成192.168.25.1

2、配置宿主机虚拟网卡

打开宿主机的网络适配器,根据上图找到NAT模式对应的网卡,这里是VMnet8:

右键属性配置该虚拟网卡:

3、配置虚拟机的网卡

setup配置

最简单的配置方式就是使用命令setup

上下选择菜单项,Tab键切换到红色按钮或者菜单项。

这里为了后续使用SSH远程连接客户端连接虚拟机,这里不启用DHCP向网关动态获取IP,而是用静态IP192.168.25.200

配置文件配置

除了使用setup命令,我们也可以通过修改/etc/sysconfig/network-scripts/ifcfg-eth0来配置:

DEVICE=eth0
TYPE=Ethernet  #以太网协议
ONBOOT=yes     #是否开机启用
BOOTPROTO=static   #ip地址设置为静态
IPADDR=192.168.0.200
NETMASK=255.255.255.0
GATEWAY=192.168.25.1 #通过网关访问外网

为了确保配置即刻生效,service network restart重启网络服务。或者由于只更改了一张网卡的配置,可以通过ifconfig eth0 downifconfig eth0 up重启网卡。

在宿主机ping虚拟机发现能够ping通了:

C:\Users\zaw>ping 192.168.25.200

正在 Ping 192.168.25.200 具有 32 字节的数据:
来自 192.168.25.200 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.25.200 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.25.200 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.25.200 的回复: 字节=32 时间<1ms TTL=64

同时在宿主机上ping外网发现也能够ping通,至此虚拟网络和外网互联了:

值得注意的是,NAT模式根本不关心宿主机的物理网卡,而只关心其虚拟网卡VMnet8,因此当宿主机物理网卡的IP更改时(即宿主机连接不同的外网时),虚拟网络仍然能访问外网(即虚拟机仍能访问外网),这也是NAT模式和桥接模式最大区别,即NAT模式能够虚拟出一个网段以隔绝虚拟网络和外网。

桥接模式

桥接模式下,所有的虚拟机是桥接在宿主机上的,相当于中间使用了一个集线器,这种情况下虚拟机IP处于宿主机和外网连接的网段下才能访问外网。这必然受宿主机物理网卡的实际IP的牵制,由于我们开发时的个人电脑连接的网络可能会更改而且使用DHCP从互联网提供商获取IP来上网时也会导致IP的改变。因此为了避免频繁配置虚拟机IP,通常使用NAT方式比较方便。

仅主机模式

这种模式下,虚拟机的眼里只有宿主机,无法访问外网。

克隆之后的网卡问题

有时我们为了在本机上模拟集群操作,需要从一个minimal版的Linux克隆出多个Linux

注意克隆类型选择创建完整克隆,克隆出来的才是一台独立的主机

但是克隆出来的主机网卡eth0和源主机冲突(每个主机都只能有唯一的物理地址),于是VMware为其生成了一块新的网卡eth1而停用了eth0

首先我们需要修改/etc/sysconfig/network-scripts/ifcfg-eth0(删除其中的UUID,HWADDR,配置静态IP):

然后修改/etc/udev/rules.d/70-persistent-net.rules

最后reboot使之生效:

[root@mini01 ~]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0C:29:98:24:D9
          inet addr:192.168.25.202  Bcast:192.168.25.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe98:24d9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:67 errors:0 dropped:0 overruns:0 frame:0
          TX packets:73 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:10455 (10.2 KiB)  TX bytes:14432 (14.0 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:20 errors:0 dropped:0 overruns:0 frame:0
          TX packets:20 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1472 (1.4 KiB)  TX bytes:1472 (1.4 KiB)

SSH

远程连接

通常我们是通过SSH客户端来远程操作Linux服务器的,而Linux默认就内置了SSH服务程序,我们可以通过netstat -nltp来查看:

于是我们就可以在本地通过常用的SSH客户端工具SecureCRT进行登录连接,协议选择SSH,端口22,输入用户名和密码点击连接即可。

免密登录

Linux也提供了ssh客户端工具,以ssh命令的形式存在,最常使用的格式是:ssh [<user>@]<hostname>,但是这种登录方式每次都需要输入密码,而ssh还提供了另一种免密登录方式,其原理如下:

machine1要想免密登录machine2首先要通过ssh-keygen通过rsa算法生成一对非对称加密的秘钥对(将保存在/root/.ssh中):

[root@hadoop01 ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
74:d1:f2:65:fc:d9:95:51:b9:a3:54:66:67:46:0a:ac root@hadoop01
The key's randomart image is:
+--[ RSA 2048]----+
|          .o.. oB|
|          ..o.+B=|
|        . .+ o=+*|
|       . .E .. +o|
|        S   . . .|
|             .   |
|                 |
|                 |
|                 |
+-----------------+

[root@hadoop01 ~]# ll .ssh/
总用量 8
-rw-------. 1 root root 1675 6月   6 09:44 id_rsa
-rw-r--r--. 1 root root  395 6月   6 09:44 id_rsa.pub

其中id_rsa.pub称为公钥,id_rsa称为私钥,公钥用来加密,私钥用来解密。公钥用来复制到要登录的目标主机的受信任列表authorized_keys中,可以借助ssh-copy-id <hostname>来完成:

[root@hadoop01 ~]# ssh-copy-id 192.168.25.201
The authenticity of host '192.168.25.201 (192.168.25.201)' can't be established.
RSA key fingerprint is eb:89:4f:4e:f5:9d:00:d4:14:1c:8b:8d:93:0e:3c:00.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.25.201' (RSA) to the list of known hosts.
root@192.168.25.201's password:
Now try logging into the machine, with "ssh '192.168.25.201'", and check in:

  .ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

查看192.168.25.201的受信任列表:

[root@mini01 ~]# cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAr/2gtvBX87wo9iSW+yTwGwmVbOpMmWYrgj8Tbl9VsBv/vCd6ktOg5Gwppb9NkVa8lj3FkN0UOOe6/xI7dr3C4+5kxvoo6GIHy/9mO67Rndo1YAZZ7UlPaJb5Kb8rkDcwX/KeylPTnrclykaBM5YypZSTr+pqZpiYAmaozLnBtzQnWgX6ZK4ijcS+psSI+bAeXZmyjAdY8qQ7Ncv3Lgr/jENL34letB9c1wOnOGSf+GkcO6hL9+n8FwlC2bld91noR17W+YQvyhdXdbK+DGPSDqbsCzlQHFJsbttBlFQZk8ErOU5GlUCiFXZzWJ3ItSC0+q/+TylU1MOkM7Ejno1/fQ== root@hadoop01

其中的表项就是由id_rsa.pub中的内容和远程登录信息root@hadoop01组成。以后当hadoop01机器上的root用户远程登录到192.168.25.201时,201发现在自己的受信任列表中包含了root@hadoop01于是会用这个表项对应的公钥加密一个随机字符串发送到企图连接到201的机器上,如果该机器真的是hadoop01而不是伪装的,那么它就能用自己的私钥将密文解密并返给201201发现解密后的正确才会让其登录。因为每个主机的私钥唯一,因此只要自己不泄露,其他主机就无法伪装成hadoop01登录201

文件查看

  • cat:滚屏输出文件所有内容
  • more:翻页查看文件
    • b上一页
    • 空格下一页
    • q退出
  • less:翻页查看文件,比more更强大,除了b、空格之外,还有
    • ↑↓翻行
    • /keyword查找,n下一个关键字,N上一个
    • gg跳到首行
    • G跳到末行
  • tail,查看文件尾部
    • tail -10,查看文件最后十行
    • tail -f/F,查看文件内容,当有内容追加到文尾时实时刷新。-f是根据文件的inode来追中文件的,而-F是根据文件名来追踪文件的。如果使用log4j,可能会遇到向xx.log中持续输出日志,当xx.log大小达到4KB的时候就将其保存为xx.log-1这种机制。这时要想持续跟踪日志动态,就要选择-F
  • head -<N>,查看文件首部

vi编辑器

快捷键(一般模式下使用)

  • a,光标后一位插入
  • A,该行行尾插入
  • I该行行首插入
  • o,从该行的下一行插入空行并开始编辑
  • gg,跳到文件的首行
  • G,跳到文件的末行
  • yy,复制本行,nyy表示复制从光标往下的n行
  • dd,删除本行,ndd表示删除从光标往下的n行
  • p,粘贴已复制的内容
  • v,进入字符选择模式,可按y复制,p粘贴
  • ctrl v,进入块选择模式
  • shift v,批量选中行
  • %s/abc/123,将文件中的所有abc替换为123,s是substitude(替换)的首字母
  • /abc,从光标之后查找abcn查找下一个,N查找上一个
  • u,撤销上一次操作
  • shift + DoubleClick z,按住shift连按两下z,保存并退出

权限

文件权限

  • 所有者:u
  • 所属组:g
  • 其他用户:o

增加权限:chmod u/g/o +r/w/x,取消权限:-r/w/x

r、w、x的权限值可表示为4、2、1

递归给文件夹中的所有文件赋予权限:chmod -R

用户管理

  • useradd <username>
  • passwd <username>,为新添加的用户设置密码或为已有的用户更改密码

上述命令只有root才有权限执行

为了避免不可逆的破坏操作系统的操作发生,实际应用中通常不用root身份登录OS。此时如果想执行类似的受限命令,我们需要在命令前加上sudo

[root@hadoop ~]# su hadoop
[hadoop@hadoop root]$ useradd tom
bash: /usr/sbin/useradd: 权限不够

[hadoop@hadoop root]$ sudo useradd tom

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for hadoop:
hadoop 不在 sudoers 文件中。此事将被报告。

su [username],通过用户名切换到指定用户,若未指定用户名则默认切换到root

上述我们切换到普通用户hadoop并试图通过sudo再次执行受限命令,却又被提示hadoop用户不在sudoers文件中。

这是因为普通用户要想通过sudo片刻获得执行某些特权命令必须让root事先在/etc/sudoers中添加相关的配置,如配置hadoop可以在任何位置执行任何命令(这是最大的权限范围,也是root的):

[hadoop@hadoop root]$ su	
密码:

[root@hadoop ~]# vi /etc/sudoers
...
## Next comes the main part: which users can run what software on
## which machines (the sudoers file can be shared between multiple
## systems).
## Syntax:
##
##      user    MACHINE=COMMANDS
##
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
hadoop  ALL=(ALL)       ALL		#配置hadoop可以在哪些地方执行哪些特权命令
...

/etc/sudoers默认是只读的,可通过:wq!强制保存。

于是hadoop就可以执行特权命令了:

[root@hadoop testvi]# su hadoop
[hadoop@hadoop testvi]$ sudo useradd tom
[sudo] password for hadoop:

[hadoop@hadoop testvi]$ sudo passwd tom
更改用户 tom 的密码 。
新的 密码:
无效的密码: WAY 过短
无效的密码: 过于简单
重新输入新的 密码:
passwd: 所有的身份验证令牌已经成功更新。

挂载

Linux是没有磁盘这一概念的,所有的外设通过挂载到目录树上通过访问文件一样来访问。

以访问光驱为例,我们在安装系统的时候设置了使用CentOS-6.7-x86_64-bin-DVD1.iso,接着我们将其挂载到目录树上。

首先我们要将这个光驱(映像文件)“插入”虚拟机:

它会被默认挂载到/media下,我们可以通过/media来访问:

[root@hadoop media]# ls
CentOS_6.7_Final
[root@hadoop media]# cd CentOS_6.7_Final/
[root@hadoop CentOS_6.7_Final]# ls
CentOS_BuildTag  GPL       Packages                  RPM-GPG-KEY-CentOS-6           RPM-GPG-KEY-CentOS-Testing-6
EFI              images    RELEASE-NOTES-en-US.html  RPM-GPG-KEY-CentOS-Debug-6     TRANS.TBL
EULA             isolinux  repodata                  RPM-GPG-KEY-CentOS-Security-6

但是光驱实体是/dev/cdrom,我们可以手动将其挂载到一个自定义的目录/mnt/cdrom中:

[root@hadoop CentOS_6.7_Final]# mkdir /mnt/cdrom
[root@hadoop CentOS_6.7_Final]# mount -t iso9660 -o ro /dev/cdrom /mnt/cdrom/
[root@hadoop CentOS_6.7_Final]# ll /mnt/cdrom/
总用量 558
-r--r--r--. 2 root root     14 8月   5 2015 CentOS_BuildTag
dr-xr-xr-x. 3 root root   2048 8月   5 2015 EFI
-r--r--r--. 2 root root    212 11月 27 2013 EULA
-r--r--r--. 2 root root  18009 11月 27 2013 GPL
dr-xr-xr-x. 3 root root   2048 8月   5 2015 images
dr-xr-xr-x. 2 root root   2048 8月   5 2015 isolinux
dr-xr-xr-x. 2 root root 528384 8月   5 2015 Packages
-r--r--r--. 2 root root   1354 7月  25 2015 RELEASE-NOTES-en-US.html
dr-xr-xr-x. 2 root root   4096 8月   5 2015 repodata
-r--r--r--. 2 root root   1706 11月 27 2013 RPM-GPG-KEY-CentOS-6
-r--r--r--. 2 root root   1730 11月 27 2013 RPM-GPG-KEY-CentOS-Debug-6
-r--r--r--. 2 root root   1730 11月 27 2013 RPM-GPG-KEY-CentOS-Security-6
-r--r--r--. 2 root root   1734 11月 27 2013 RPM-GPG-KEY-CentOS-Testing-6
-r--r--r--. 1 root root   3380 8月   5 2015 TRANS.TBL

其中-t iso9660是指文件系统类型,-o ro是指挂载后的目录read only

umount则可取消挂载:

[root@hadoop CentOS_6.7_Final]# umount /mnt/cdrom/
[root@hadoop CentOS_6.7_Final]# ls /mnt/cdrom/
[root@hadoop CentOS_6.7_Final]#

系统信息

基本信息

  • uname,查看系统基本信息,如OS位数

  • free -m,查看内存使用情况,以MB为单位

  • top,查看进程列表相当于打开任务管理器,q退出

  • hostname,查看或设置主机名

    [root@hadoop testvi]# hostname
    hadoop.com
    [root@hadoop testvi]# hostname hadoop01
    [root@hadoop testvi]# hostname
    hadoop01
    

    但此设置在重启后就会失效,要想永久生效需要修改/etc/sysconfig/network

    [root@hadoop testvi]# vi /etc/sysconfig/network
    NETWORKING=yes
    HOSTNAME=hadoop01
    NTPSERVERARGS=iburst
    
  • ifconfig eth0 <new ip>,修改IP,重启后失效。永久生效需使用setup或修改/etc/sysconfig/network-scripts/ifcfg-eth0

  • df -h,查看磁盘信息:

    [root@hadoop CentOS_6.7_Final]# df -h
    Filesystem            Size  Used Avail Use% Mounted on
    /dev/mapper/vg_hadoop-lv_root
                           18G  3.6G   13G  22% /
    tmpfs                 996M  224K  996M   1% /dev/shm
    /dev/sda1             477M   42M  410M  10% /boot
    /dev/sr0              3.7G  3.7G     0 100% /media/CentOS_6.7_Final
    
  • du -sh,查看文件大小

    [root@hadoop ~]# ll
    总用量 104
    -rw-------. 1 root root  1615 6月   4 2019 anaconda-ks.cfg
    -rw-r--r--. 1 root root 46328 6月   4 2019 install.log
    -rw-r--r--. 1 root root 10033 6月   4 2019 install.log.syslog
    drwxr-xr-x. 2 root root  4096 6月   4 15:25 testvi
    drwxr-xr-x. 2 root root  4096 6月   4 2019 公共的
    drwxr-xr-x. 2 root root  4096 6月   4 2019 模板
    drwxr-xr-x. 2 root root  4096 6月   4 2019 视频
    drwxr-xr-x. 2 root root  4096 6月   4 2019 图片
    drwxr-xr-x. 2 root root  4096 6月   4 2019 文档
    drwxr-xr-x. 2 root root  4096 6月   4 2019 下载
    drwxr-xr-x. 2 root root  4096 6月   4 2019 音乐
    drwxr-xr-x. 2 root root  4096 6月   4 2019 桌面
    
    [root@hadoop ~]# du -sh *
    4.0K    anaconda-ks.cfg
    52K     install.log
    12K     install.log.syslog
    20K     testvi
    4.0K    公共的
    4.0K    模板
    4.0K    视频
    4.0K    图片
    4.0K    文档
    4.0K    下载
    4.0K    音乐
    4.0K    桌面
    

服务管理

  • service
    • service --status-all,查看所有服务的运行状态,类似于Windows下的services.msc
    • service <process> stop,停止某服务
    • service <process> status,查看某服务的状态
    • service <process> start,启用某服务
    • service <process> restart,重启某服务
  • chkconfig,设置服务启动类型
    • chkconfig iptables off,设置防火墙开机不自启
    • chkconfig iptables on,设置开机自启
    • chkconfig iptables --list,查看防火墙启动类型(分6种Linux启动模式,可在/etc/inittab中查看)
  • netstat -nltp,查看正在监听的端口及其服务

软件安装

获取安装包

  • 使用wget从网上下载
  • 使用的SSH客户端是MobaXterm,可以直接拖拽文件到Linux目录树
  • 使用的SSH客户端是SecureCRT,在命令行中使用ALT + P激活sftp工具,使用put命令跟上安装包在你宿主机上的全路径(或直接拖入)。在sftp环境下可使用的命令:
    • put <filepath>,将宿主机上的文件上传到虚拟机,默认上传到当前用户的主目录
    • get <filepath>,将虚拟机上的文件下载到宿主机
    • cd <path>,设置上传到虚拟机的文件的保存目录
    • lcd <path>,设置下载到宿主机的文件的保存目录,如lcd d:/

压缩/解压

  • gzip,压缩/解压

    • gzip <file>,压缩,后缀gz

    • gzip -d <file>,解压

      [root@mini01 ~]# ls
      anaconda-ks.cfg  install.log  install.log.syslog
      
      [root@mini01 ~]# gzip install.log
      [root@mini01 ~]# ls
      anaconda-ks.cfg  install.log.gz  install.log.syslog
      
      [root@mini01 ~]# gzip -d install.log.gz
      [root@mini01 ~]# ls
      anaconda-ks.cfg  install.log  install.log.syslog
      
  • tar,打包/解包

    • tar -cvf <target> <source1> <source2> ...

      [root@mini01 ~]# mkdir aaa
      [root@mini01 ~]# mkdir bbb
      [root@mini01 ~]# echo 11 > aaa/1.txt
      [root@mini01 ~]# echo 22 > bbb/2.txt
      [root@mini01 ~]# tar cvf mypackage.tar aaa bbb
      aaa/
      aaa/1.txt
      bbb/
      bbb/2.txt
      [root@mini01 ~]# ls
      aaa  anaconda-ks.cfg  bbb  install.log  install.log.syslog  mypackage.tar
      

      -c:创建一个tar包,-v显示包含了哪些文件,-f <target>指定打包生成文件的名称

    • tar -xvf <tar>

      [root@mini01 ~]# rm -rf aaa bbb
      [root@mini01 ~]# tar xvf mypackage.tar
      aaa/
      aaa/1.txt
      bbb/
      bbb/2.txt
      [root@mini01 ~]# ls
      aaa  anaconda-ks.cfg  bbb  install.log  install.log.syslog  mypackage.tar
      

    通常打包和压缩一次性完成:tar zcvf,解压和解包也是:tar zxvf(可通过-C <path>指定解压到指定目录)

环境变量

/etc/profile中配置,source /etc/profile使之生效

RPM

RPM是软件包管理器

  • rpm -ivh xxx.rpm安装某个软件包
  • rmp -e xxx –-nodeps,如果已有的软件A和要安装的软件包B冲突,可用此先删除再安装;如果已有的软件C依赖软件A,那么就要添加--nodeps忽略删除导致的后果并强行删除。
  • rpm -qa,查询系统中安装的RPM包

YUM

作用相当于maven,帮助我们一站式解决软件安装过程中的寻找依赖和依赖版本冲突问题。

常用命令

  • yum install -y xxx,不询问直接安装软件及其所需依赖
  • yum list,列出所有可用的packagepackage
  • yum clean all,清除所有缓冲数据
  • yum deplist xxx,列出一个包所有依赖的包
  • yum remove xxx,卸载
  • yum repolist,列出可用的YUM源

制作本地YUM源

YUM源其实就是一个保存了多个RPM包的服务器,可以通过http的方式来检索、下载并安装相关的RPM包。但是当开发环境不能联网时,我们就需要制作一个本地YUM源。可以利用我们安装虚拟机时用的CentOS-6.7-x86_64-bin-DVD1.iso,其中就有很多包。

首先我们要在虚拟机的设置中的CD/DVD设置为使用ISO映像文件,再选择CentOS-6.7-x86_64-bin-DVD1.iso的路径。然后右键虚拟机->可移动设备->连接。将其挂载到目录树上:

[root@mini01 ~]# mount -t iso9660 -o ro /dev/cdrom /mnt/cdrom
[root@mini01 ~]# ls /mnt/cdrom
CentOS_BuildTag  isolinux                  RPM-GPG-KEY-CentOS-Debug-6
EFI              Packages                  RPM-GPG-KEY-CentOS-Security-6
EULA             RELEASE-NOTES-en-US.html  RPM-GPG-KEY-CentOS-Testing-6
GPL              repodata                  TRANS.TBL
images           RPM-GPG-KEY-CentOS-6

[root@mini01 ~]# ls /mnt/cdrom/repodata/
40eeab440905d20a31dd7db33fa8724fba260bcb1047fb6488027b85c22876d2-filelists.sqlite.bz2
486d3ee62873814293a1be370640ae9c71863a35c7299eb76739e03369ad0c3f-c6-x86_64-comps.xml.gz
4df092633ebecaeebdd78359a11a3c13f619f22605322e15e5e307beebd8e641-c6-x86_64-comps.xml
80ae77a0d8cca9c7a3d3361feb4efe0c0c9a876679c68aa81c1852b03ce8339a-filelists.xml.gz
baa4a6f9f3595b30299024b2b1dda93276cb7c2cded3ecea35119a140f6ad14f-primary.xml.gz
bd821d6fb163fc5508b3caa407480faa51a2223e6f475da95675b84c716d6474-other.sqlite.bz2
c11b211333eadda7b2e2d0f7fa8ffbf70a1d32d5182babbb43b90427578e2891-primary.sqlite.bz2
c51255b1b9faf7ce2d5ccaf96cf1b2887ec5c3e1524a45f6dee1f1954accbb46-other.xml.gz
repomd.xml
TRANS.TBL

其中的Packages中就包含了很多常用的软件包,而repodata/xxx.xml相当于maven中的pom,用于找到软件包的位置以及个软件包之间的依赖关系。

配置YUM源我们需要修改/etc/yum.repos.d/中的配置文件:

[root@mini01 yum.repos.d]# ls
CentOS-Base.repo       CentOS-fasttrack.repo  CentOS-Vault.repo
CentOS-Debuginfo.repo  CentOS-Media.repo

其中Centos-Base.repo中配置了官方的YUM源,其服务器在国外,如果下载速度慢可以换成网易的镜像源(下载网易提供的CentOS-Base.repo来替换)。CentOS-Media.repo则是配置本地YUM源的一个模板,我们将其指向刚挂载的/mnt/cdrom(也即repodata所在的目录):

[root@mini01 yum.repos.d]# vi CentOS-Media.repo
[c6-media]
name=CentOS-$releasever - Media
baseurl=file:///mnt/cdrom
gpgcheck=1
enabled=1	#设置为1才启用
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

仅使用该YUM源时可以将其它几个YUM源配置文件更名,以免影响:

[root@mini01 yum.repos.d]# rename .repo .repo.bak *
[root@mini01 yum.repos.d]# mv CentOS-Media.repo.bak CentOS-Media.repo
[root@mini01 yum.repos.d]# ls
CentOS-Base.repo.bak       CentOS-fasttrack.repo.bak  CentOS-Vault.repo.bak
CentOS-Debuginfo.repo.bak  CentOS-Media.repo

yum clean all清除缓冲,yum repolist查看可用YUM源:

[root@mini01 yum.repos.d]# yum clean all
已加载插件:fastestmirror
Cleaning repos: c6-media
清理一切
Cleaning up list of fastest mirrors
[root@mini01 yum.repos.d]# yum repolist
已加载插件:fastestmirror
Determining fastest mirrors
c6-media                                                                     | 4.0 kB     00:00 ...
c6-media/primary_db                                                          | 4.6 MB     00:00 ...
仓库标识                                   仓库名称                                            状态
c6-media                                   CentOS-6 - Media                                    6,575
repolist: 6,575

MySQL

环境

  • CentOS安装版本:Desktop(如果是Minimal会缺少很多依赖导致安装过程很复杂,推荐使用Desktop)
  • MySQL-5.5.37-1.el6.x86_64.rpm-bundle.tar,MySQL相关组件安装包集

bundle上传至虚拟机并解压:

[root@hadoop01 ~]# mkdir mysql-bundle
[root@hadoop01 ~]# tar xvf MySQL-5.5.37-1.el6.x86_64.rpm-bundle.tar -C mysql-bundle/
MySQL-shared-compat-5.5.37-1.el6.x86_64.rpm
MySQL-server-5.5.37-1.el6.x86_64.rpm
MySQL-devel-5.5.37-1.el6.x86_64.rpm
MySQL-embedded-5.5.37-1.el6.x86_64.rpm
MySQL-client-5.5.37-1.el6.x86_64.rpm
MySQL-test-5.5.37-1.el6.x86_64.rpm
MySQL-shared-5.5.37-1.el6.x86_64.rpm
[root@hadoop01 ~]# cd mysql-bundle/
[root@hadoop01 mysql-bundle]# ls
MySQL-client-5.5.37-1.el6.x86_64.rpm    MySQL-shared-5.5.37-1.el6.x86_64.rpm
MySQL-devel-5.5.37-1.el6.x86_64.rpm     MySQL-shared-compat-5.5.37-1.el6.x86_64.rpm
MySQL-embedded-5.5.37-1.el6.x86_64.rpm  MySQL-test-5.5.37-1.el6.x86_64.rpm
MySQL-server-5.5.37-1.el6.x86_64.rpm

安装MySQL服务器:

[root@hadoop01 mysql-bundle]# rpm -ivh MySQL-server-5.5.37-1.el6.x86_64.rpm
Preparing...                ########################################### [100%]
        file /usr/share/mysql/charsets/Index.xml from install of MySQL-server-5.5.37-1.el6.x86_64 conflicts with file from package mysql-libs-5.1.73-5.el6_6.x86_64
        file /usr/share/mysql/charsets/armscii8.xml from install of MySQL-server-5.5.37-1.el6.x86_64 conflicts with file from package mysql-libs-5.1.73-5.el6_6.x86_64
...

上述报错,说我们安装的MySQL-server-5.5.37mysql-libs-5.1.73有冲突,后者可能是安装系统时自带的,我们将后者删除在安装:

[root@hadoop01 mysql-bundle]# rpm -e mysql-libs-5.1.73-5.el6_6.x86_64 --nodesps
--nodesps: 未知的选项
[root@hadoop01 mysql-bundle]# rpm -e mysql-libs-5.1.73-5.el6_6.x86_64 --nodeps
[root@hadoop01 mysql-bundle]# rpm -ivh MySQL-server-5.5.37-1.el6.x86_64.rpm
Preparing...                ########################################### [100%]
   1:MySQL-server           ########################################### [100%]

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h hadoop01 password 'new-password'

Alternatively you can run:
/usr/bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

Please report any problems at http://bugs.mysql.com/

上述提示我们要设置MySQL的root密码,首先要启动服务,然后使用/usr/bin/mysqladmin/usr/bin/mysql_secure_installaion命令:

[root@hadoop01 mysql-bundle]# /usr/bin/mysql_secure_installation
Can't find a 'mysql' client in PATH or ./bin

它又提示没有安装mysql client,于是我们先安装它:

[root@hadoop01 mysql-bundle]# rpm -ivh MySQL-client-5.5.37-1.el6.x86_64.rpm
Preparing...                ########################################### [100%]
   1:MySQL-client           ########################################### [100%]
   
[root@hadoop01 mysql-bundle]# /usr/bin/mysql_secure_installation




NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!


In order to log into MySQL to secure it, we'll need the current
password for the root user.  If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):	#回车
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.

Set root password? [Y/n] Y
New password:	#设置root密码,我设置为root
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] n	#是否禁止远程登录
 ... skipping.

By default, MySQL comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y	#刷新权限表,必须是y
 ... Success!

Cleaning up...



All done!  If you've completed all of the above steps, your MySQL
installation should now be secure.

Thanks for using MySQL!

于是就可以使用MySQL了:

[root@hadoop01 mysql-bundle]# mysql -uroot -proot
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.5.37 MySQL Community Server (GPL)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

Shell编程

脚本执行方式

  • bash+ 脚本

  • sh+ 脚本

    [root@mini01 ~]# mkdir shell
    [root@mini01 ~]# cd shell/
    [root@mini01 shell]# vi helloworld.sh
    #!/bin/bash
    echo helloworld
    
    [root@mini01 shell]# bash helloworld.sh
    helloworld
    [root@mini01 shell]# sh helloworld.sh
    helloworld
    [root@mini01 shell]#
    

    最好养成在脚本行首注明用哪个解释器解释执行的习惯!

  • 赋予执行权限直接运行:

    [root@mini01 shell]# chmod u+x helloworld.sh
    [root@mini01 shell]# ./helloworld.sh
    helloworld
    
  • 在当前bash环境下运行:

    [root@mini01 shell]# vi helloworld.sh
    #!/bin/bash
    aaa=helloworld
    
    [root@mini01 shell]# ./helloworld.sh
    [root@mini01 shell]# echo $aaa
    
    [root@mini01 shell]# . ./helloworld.sh
    [root@mini01 shell]# echo $aaa
    helloworld
    

    如果直接通过脚本路径执行脚本那么会让其在一个新的bash环境下执行,如果在前面再加上一个.则会在当前bash环境下执行,bash环境不同的脚本之间无法共享变量。

    [root@mini01 shell]# vi helloworld.sh
    #!/bin/bash
    aaa=helloworld
    sleep 20
    
    [root@mini01 shell]# . ./helloworld.sh &
    [1] 1483
    [root@mini01 shell]# pstree
    init─┬─auditd───{auditd}
         ├─crond
         ├─dbus-daemon───{dbus-daemon}
         ├─master─┬─pickup
         │        └─qmgr
         ├─6*[mingetty]
         ├─rsyslogd───3*[{rsyslogd}]
         ├─sshd─┬─sshd───bash─┬─bash───sleep
         │      │             └─pstree
         │      └─sshd───sftp-server
         └─udevd───2*[udevd]
    

变量操作

  • set,查看当前的环境变量有哪些

  • unset 变量名,撤销变量,但readonly定义的变量无法撤销

  • $变量名,引用变量

    [root@mini01 shell]# echo $PATH
    /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
    [root@mini01 shell]# echo $PWD
    /root/shell
    
  • 变量名=变量值,该变量仅在本次会话内有效(即在重启后或其他会话内无效),要想永久生效需在/etc/profile中配置并使用source /etc/profile刷新

  • 变量名="变量值",当变量值包含空格时需用双引号将其整体括起来,以将空格脱意(空格的本意是用来分割命令和参数、参数和参数)

    [root@mini01 shell]# aaa=hello world
    -bash: world: command not found
    [root@mini01 shell]# aaa="hello world"
    [root@mini01 shell]#
    

    但双引号仅使变量值中的空格脱意,其他特殊字符如变量引用符$则仍然解析:

    [root@mini01 shell]# x=hello
    [root@mini01 shell]# y="$x world"
    [root@mini01 shell]# echo $y
    hello world
    

    这时要想y的变量值原样显示,则需使用单引号

  • 变量名='变量值',单引号会脱意变量值中的任何特殊字符

    [root@mini01 shell]# y='$x world'
    [root@mini01 shell]# echo $y
    $x world
    
  • export 变量名,可以将变量提升为全局变量,可供其他shell使。source就是将文件中的export执行一遍。

  • 变量名=$(命令)(或使用反引号)可以将命令的执行结果作为变量值复制给变量:

[root@mini01 shell]# wc -c helloworld.sh
36 helloworld.sh

[root@mini01 shell]# wc -c helloworld.sh | cut -d ' ' -f 1  #统计文件的字节数
36

[root@mini01 shell]# wordcount=`wc -c helloworld.sh | cut -d ' ' -f1`
[root@mini01 shell]# echo $wordcount
36
[root@mini01 shell]# wordcount=$(wc -c helloworld.sh | cut -d ' ' -f1)
[root@mini01 shell]# echo $wordcount
36

Shell中的特殊变量

  • $?,上一条命令的退出状态(即程序返回值),如果程序没有返回值则表示程序退出的状态码,那么$?为0表示成功执行,非0则表示执行失败

    [root@mini01 shell]# ls -la			
    总用量 12	#这些只是命令执行过程中的输出而不是返回值
    drwxr-xr-x. 2 root root 4096 6月   7 19:41 .
    dr-xr-x---. 6 root root 4096 6月   7 19:43 ..
    -rwxr--r--. 1 root root   36 6月   7 19:41 helloworld.sh
    [root@mini01 shell]# echo $?
    0
    [root@mini01 shell]# lss
    -bash: lss: command not found
    [root@mini01 shell]# echo $?
    127
    

    如果程序有返回值,那么$?就是该值(如truefalse就有返回值):

    [root@mini01 shell]# true
    [root@mini01 shell]# echo $?
    0
    [root@mini01 shell]# false
    [root@mini01 shell]# echo $?
    1
    
  • $$,当前进程编号

  • $0,当前脚本名称

  • $#,参数个数

  • $*/$@,参数列表

    [root@mini01 shell]# vi helloworld.sh
    #!/bin/bash
    for p in $*
    do
            echo $p
    done
    
    for p in $@
    do
            echo $p
    done
    
    [root@mini01 shell]# ./helloworld.sh p1 p2 p3 p4
    p1
    p2
    p3
    p4
    p1
    p2
    p3
    p4
    

    两者的区别是,加双引号时,“$*”会作为一个整体,而“$@”仍然以“$1” “$2” “$3”...的形式存在:

    [root@mini01 shell]# vi helloworld.sh
    #!/bin/bash
    for p in "$*"
    do
            echo $p
    done
    
    for p in "$@"
    do
            echo $p
    done
    
    [root@mini01 shell]# ./helloworld.sh p1 p2 p3 p4
    p1 p2 p3 p4
    p1
    p2
    p3
    p4
    
  • $n,n位置的输入参数,n代表数字

运算符

格式:expr m + n$((m+n)),注意:expr以及+的两边必须有一个空格

(2+3)*4的计算为例:

[root@mini01 shell]# res=(2+3)*4
[root@mini01 shell]# echo $res
(2+3)*4
[root@mini01 shell]# res=`expr 2 + 3`
[root@mini01 shell]# echo $res
5
[root@mini01 shell]# expr $res \* 4
20

一步得出结果:

[root@mini01 shell]# res=`expr \`expr 2 + 3\` \* 4`
[root@mini01 shell]# echo $res
20

[root@mini01 shell]# res=$(((2+3)*4))
[root@mini01 shell]# echo $res
20

流程控制

条件表达式

格式:[ <condition> ],注意[的右侧和]的左侧要有一个空格。

数字的比较:lt less than, gt great than, le less than or equal to, ge great than or equal to, eq equal to, ne not equal to

字符串比较:=

可以使用$?检测条件表达式的正确性,0为true,>0为false:

[root@mini01 shell]# [ 2 -gt 1 ]
[root@mini01 shell]# echo $?
0
[root@mini01 shell]# [ 2 -eq 3 ]
[root@mini01 shell]# echo $?
1

字符串的判断为true:

[root@mini01 shell]# [ abc ]
[root@mini01 shell]# echo $?
0

可以借助&&||实现如果condition1成立则执行command1否则执行command2的效果:

[root@mini01 shell]# [ 1 -gt 2 ] && echo yes || echo no
no

文件相关的判断[ -r xx.sh]

  • -r 有读的权限
  • -w 有写的权限
  • -x 有执行的权限
  • **-**f 文件存在并且是一个常规的文件
  • -s 文件存在且不为空
  • -d 文件存在并是一个目录
  • -b文件存在并且是一个块设备
  • -L 文件存在并且是一个链接

for循环

  • for in

    [root@mini01 shell]# for N in 1 2 3
    > do
    > echo $N
    > done
    1
    2
    3
    
    [root@mini01 shell]# for N in 1 2 3;do echo $N;done
    1
    2
    3
    
    [root@mini01 shell]# for N in {1..3}
    > do
    > echo $N
    > done
    1
    2
    3
    
  • for ((i=n;i<m;i++))

    [root@mini01 shell]# for ((i=1;i<=5;i++));do echo $i;done
    1
    2
    3
    4
    5
    
    [root@mini01 shell]# for ((i=1;i<=5;i++))
    > do
    > echo $i
    > done
    1
    2
    3
    4
    5
    

while循环

  • while [ <condition> ];do <command>;done

    [root@mini01 shell]# while [ 2 -gt 1 ]
    > do
    > echo "aa"
    > done
    aa
    aa
    aa
    aa
    ...
    

    注意:[]-gt的两边都必须要有一个空格。

  • while ((<condition>));do <command>;done

    [root@mini01 shell]# while ((i<=5))
    > do
    > echo $i
    > let i++
    > done
    1
    2
    3
    4
    5
    

case语句

格式:

case <var> in
item1)
	<command>
	;;
item2)
	<command>
	;;
...
*)
	<command>
esac

例:

[root@mini01 shell]# vi test-case.sh
#!/bin/bash
case $1 in
start)
        echo "starting..."
        ;;
stop)
        echo "stopping.."
        ;;
*)
        please enter "start" or "stop"
esac

[root@mini01 shell]# sh test-case.sh start
starting...

read命令

格式:read -p <提示信息> <变量名>,提示并获取用户的输入(-p指定提示信息),例:

[root@mini01 shell]# sh test-read.sh
please enter your password:123
your input is 123

if判断

格式:

if [ <condition> ]
	then
		<command>
elif [ <condition> ]
	then
		<command>
elif [ <condition> ]
	then 
		<command>
else
	<command>
fi

例:

[root@mini01 shell]# vi test-if.sh
#!/bin/bash
read -p "please input your grade:" GRADE
if [ $GRADE -ge 90 ]
        then echo A
elif [ $GRADE -ge 60 ]
        then echo B
else
        echo C
fi

[root@mini01 shell]# sh test-if.sh 86
please input your grade:86
B
[root@mini01 shell]# sh test-if.sh
please input your grade:86
B
[root@mini01 shell]# sh test-if.sh
please input your grade:54
C
[root@mini01 shell]# sh test-if.sh
please input your grade:99
A

自定义函数

格式:

function <函数名>() / function <函数名> / <函数名>()
{
	action...
	return <int:0~255>
}

例:

[root@mini01 shell]# vi sum.sh
#!/bin/bash
function sum()
{
        return `expr $1 + $2`;
}
sum 1 2;
res=$?;
echo $res;

[root@mini01 shell]# sh sum.sh
3

注意:

1.必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先预编译

2.函数返回值,只能通过$? 系统变量获得,函数体末尾可以显式地加return返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)

脚本调试

  • sh -vx xx.sh
[root@mini01 shell]# vi sum.sh
#!/bin/bash
function sum()
{
        return `expr $1 + $2`;
}
sum 1 2;
res=$?;
echo $res;

[root@mini01 shell]# sh -vx sum.sh
#!/bin/bash
function sum()
{
        return `expr $1 + $2`;
}
sum 1 2;
+ sum 1 2
expr $1 + $2
++ expr 1 + 2
+ return 3
res=$?;
+ res=3
echo $res;
+ echo 3
3

高级文本处理命令

cut

cut命令可以从一个文本文件或者文本流中提取文本列:

  • 若有特定分隔符:cut -d'分隔字符' -f fields,以分隔符分割并取出第fields
    • -d,delimiters
    • -f,fregment
  • 若排列整齐:cut -c 字符区间,以字符 (characters) 的单位取出固定字符区间
    • -c,characters

例:PATH 变量如下:

[root@www ~]# echo $PATH
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games
# 1 | 2       | 3   | 4       | 5            | 6            | 7

将 PATH 变量取出,我要找出第五个路径:

#echo $PATH | cut -d ':' -f 5
/usr/local/bin

将 PATH 变量取出,我要找出第三和第五个路径:

#echo $PATH | cut -d ':' -f 3,5
/sbin:/usr/local/bin

将 PATH 变量取出,我要找出第三到最后一个路径:

echo $PATH | cut -d ':' -f 3-
/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games

将 PATH 变量取出,我要找出第一到第三个路径:

#echo $PATH | cut -d ':' -f 1-3
/bin:/usr/bin:/sbin:

查看/etc/passwd,只显示其中的用户及其默认使用的shell解析器

[root@mini01 shell]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

[root@mini01 shell]# cat /etc/passwd | cut -d ':' -f 1,7
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
lp:/sbin/nologin
sync:/bin/sync
shutdown:/sbin/shutdown
halt:/sbin/halt
mail:/sbin/nologin
uucp:/sbin/nologin
operator:/sbin/nologin
games:/sbin/nologin
gopher:/sbin/nologin
ftp:/sbin/nologin
nobody:/sbin/nologin
dbus:/sbin/nologin
vcsa:/sbin/nologin
saslauth:/sbin/nologin
postfix:/sbin/nologin
sshd:/sbin/nologin

sort

命令对file参数指定的文件或标准输入流中的行排序,并将结果写到标准输出。如果file参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序。

  • -t指定域分隔符
  • -k指定按第几个列排序
  • -n按照纯数字排序(默认以文本形式按照字典序排序)
  • -r逆序,reverse
  • -u去重,unique

查看/etc/passwd并以用户名排序:

[root@mini01 shell]# cat /etc/passwd | sort
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
...

以用户ID排序(即每行以冒号分隔的第三列排序):

[root@mini01 shell]# cat /etc/passwd | sort -t ':' -k 3 -n
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
...

/etc/passwd,先以第六个域的第2个字符到第4个字符进行正向排序,再基于第一个域进行反向排序:

cat /etc/passwd |  sort -t':' -k 6.2,6.4 -k 1r      
sync:x:4:65534:sync:/bin:/bin/sync
proxy:x:13:13:proxy:/bin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
...

uniq

uniq命令可以去除排序过的文件中的重复行,因此uniq经常和sort合用。也就是说,为了使uniq起作用,所有的重复行必须是相邻的。

例:testfile的内容如下

cat testfile
hello
world
friend
hello
world
hello

未经排序时使用uniq没有效果:

uniq testfile  
hello
world
friend
hello
world
hello

排序并去重:

cat testfile | sort |uniq
friend
hello
world

排序之后删除重复行,同时在行首位置输出该行重复的次数:

sort testfile | uniq -c
1 friend
3 hello
2 world

wc

[root@mini01 shell]# wc --help
用法:wc [选项]... [文件]...
输出每个指定文件的行数、单词计数和字节数
  -m, --chars           输出字符数统计
  -l, --lines           输出行数统计
  -w, --words                   显示单词计数

sed

sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

删除-d

  • sed '2d' example-----删除example文件的第二行。
    • 加上-i则将修改后的内容覆盖源文件
  • sed '2,$d' example-----删除example文件的第二行到末尾所有行。
  • sed '$d' example-----删除example文件的最后一行。
  • sed '/test/'d example-----删除example文件所有包含test的行。

替换-s

  • sed 's/test/mytest/g' example-----在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。
  • sed -n 's/^test/mytest/p' example-----(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。
  • sed 's/^192.168.0.1/&localhost/' example-----&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost
  • sed -n 's/\(love\)able/\1rs/p' example-----love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。
  • sed 's#10#100#g' example-----不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。

选定行的范围-逗号

  • sed -n '/test/,/check/p' example-----所有在模板test和check所确定的范围内的行都被打印。
  • sed -n '5,/^test/p' example-----打印从第五行开始到第一个包含以test开始的行之间的所有行。
  • sed '/test/,/check/s/$/sed test/' example-----对于模板test和west之间的行,每行的末尾用字符串sed test替换。

多点编辑-e

  • sed -e '1,5d' -e 's/test/check/' example-----(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执 行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。
  • sed --expression='s/test/check/' --expression='/love/d' example-----一个比-e更好的命令是--expression。它能给sed表达式赋值。

awk

是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格和Tab为默认分隔符将每行切片,切开的部分再进行各种分析处理。如查看最近5次登陆的用户:

[root@mini01 shell]# last -n 5
root     pts/1        192.168.25.2     Fri Jun  7 19:43 - 19:44  (00:00)
root     pts/0        192.168.25.2     Fri Jun  7 19:20   still logged in
reboot   system boot  2.6.32-573.el6.x Fri Jun  7 19:19 - 00:51  (05:32)
root     pts/0        192.168.25.2     Fri Jun  7 02:33 - 04:54  (02:20)
reboot   system boot  2.6.32-573.el6.x Fri Jun  7 02:23 - 00:51  (22:28)

wtmp begins Thu Jun  6 17:35:18 2019
[root@mini01 shell]# last -n 5 | awk '{print $1}'
root
root
reboot
root
reboot

每行都会执行action : {print $1}

awk中同时提供了printprintf两种打印输出的函数:

  • print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。
  • printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂

-F指定分隔符,只显示/etc/passwd的账户:

cat /etc/passwd |awk  -F ':'  '{print $1}'  
root
daemon
bin
sys
...

显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以Tab键分割:

cat /etc/passwd |awk  -F ':'  '{print $1"\t"$7}'
root    /bin/bash
daemon  /bin/sh
bin     /bin/sh
sys     /bin/sh

显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"

cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh

awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

搜索/etc/passwd有root关键字的所有行:

awk -F: '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash

匹配了pattern(这里是‘/root/’)的行才会执行action(没有指定action,默认输出每行的内容)。搜索支持正则

搜索/etc/passwd有root关键字的所有行,并显示对应的shell:

awk -F: '/root/{print $7}' /etc/passwd             
/bin/bash

标题:Linux问题汇总
作者:zanwen
地址:http://www.zhenganwen.top/articles/2019/06/04/1565048861847.html

评论