zoukankan      html  css  js  c++  java
  • Linux学习Day4:管道符、重定向与环境变量

      仅仅是学习Linux系统的命令还不够,只有把多个命令按照自己想要的方式进行组合使用,才能提高工作效率。今天的内容主要是关于如何把命令组合在一起使用,使得输入的命令更准确、更高效,也为接下来的Shell脚本打好基础。

    一、输入输出重定向


      输入重定向:指把文件内容导入到命令中。

      输出重定向:指把原本要输出到屏幕的数据信息写入到指定的文件中,又分为标准输出重定向错误输出重定向两种。

      •   标准输入重定向(STDIN,文件描述符为0):默认从键盘输入,也可以从其他文件或命令输入。
      •   标准输出重定向(STDIN,文件描述符为1):默认输出到屏幕。
      •   错误输出重定向(STDERR,文件描述符为2):默认输出到屏幕。

      要区别对待两种输出信息,第一种是命令的标准输出信息,第二种是命令的报错提示信息(错误输出),如下所示:

    [root@linuxprobe ~]# ls -l anaconda-ks.cfg 
    -rw-------. 1 root root 1032 Feb 18  2019 anaconda-ks.cfg      //ls命令的标准输出信息,也是我们想要的信息
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# ls -l xxxxx
    ls: cannot access xxxxx: No such file or directory      //因为xxxxx文件不存在,所以输出的是报错提示信息
    [root@linuxprobe ~]# 

      对于输入重定向来说,用到的符号及其作用如下所示:

    符号 作用
    命令 < 文件 将文件作为命令的标准输入
    命令 << 分界符 从标准输入中读入,直到遇见分界符才停止(分界符可以自己定义,如"EOF"、"over"等)
    命令 < 文件1 > 文件2 将文件1作为命令的标准输入并将标准输出到文件2

      对于输出重定向来说,用到的符号及其作用如下所示:

    符号 作用
    命令 > 文件 将标准输出重定向到一个文件中(清空原有文件的数据)
    命令 2> 文件 将错误输出重定向到一个文件中(清空原来文件的数据)
    命令 >> 文件 将标准输出重定向到一个文件中(追加到原有文件的后面)
    命令 2>> 文件 将错误输出重定向到一个文件中(追加到原有内容的后面)
    命令 >>  文件 2>&1  或  命令 &>> 文件 将标准输出和错误输出共同写入到文件中(追加到原有内容的后面)

      通过标准输出重定向将 man ls 命令原本要输出到屏幕的信息写入文件readme.txt中,然后显示readme.txt文件中的内容,具体命令如下:

    [root@linuxprobe ~]# man ls > readme.txt
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# cat readme.txt 
    LS(1)                                                      User Commands                                                     LS(1)
    
    
    
    NAME
           ls - list directory contents
    
    SYNOPSIS
           ls [OPTION]... [FILE]...
    
    DESCRIPTION
           List  information about the FILEs (the current directory by default).  Sort entries alphabetically if none of -cftuvSUX nor
           --sort is specified.
    ---------------------------------省略部分输出内容---------------------

      通过覆盖写入模式向readme.txt文件中写入一行数据,然后再通过追加写入模式再写入一行数据,具体命令如下:

    [root@linuxprobe ~]# echo "Welcome to my home" > readme.txt      //清除原有的内容
    [root@linuxprobe ~]# echo "Learning Linux is happy to me" >> readme.txt    //追加至原来文件内容的后面
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# cat readme.txt 
    Welcome to my home
    Learning Linux is happy to me
    [root@linuxprobe ~]# 

      如果想把命令的报错信息写入文件,该如何操作呢?

    [root@linuxprobe ~]# ls -l xxxxx
    ls: cannot access xxxxx: No such file or directory     //提示xxxxx文件不存在
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# ls -l xxxxx 2> readme.txt    //将报错信息写入readme.txt文件
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# cat readme.txt 
    ls: cannot access xxxxx: No such file or directory    //报错信息写入readme.txt文件成功
    [root@linuxprobe ~]# 

      输入重定向相对来说比较冷门,在工作中遇到的概率较小。输入重定向的作用是把文件内容直接导入命令中。接下来使用输入重定向把readme.txt文件导入给wc -l命令,统计文件内容的行数。

    [root@linuxprobe ~]# cat readme.txt 
    ls: cannot access xxxxx: No such file or directory
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# wc -l < readme.txt    //使用输入重定向
    1
    [root@linuxprobe ~]# 

    二、管道命令符


      管道符,即“|”,其执行的格式“命令A | 命令B”,当然可以这样使用:“命令A | 命令B | 命令C”。管道命令符的作用是把前一个命令A原本要输出到屏幕的标准正常数据当作是后一个命令B的标准输入,比如把搜索命令的输出值传递给统计命令,具体如下:

    [root@localhost ~]# grep "/sbin/nologin" /etc/passwd | wc -l    
    19
    [root@localhost ~]# 

      再比如用翻页的形式查看/etc目录中的文件列表及属性信息:

    [root@localhost ~]# ls -l /etc/ | more
    total 1168
    -rw-r--r--.  1 root root       16 Jun 18  2019 adjtime
    -rw-r--r--.  1 root root     1518 Jun  7  2013 aliases
    -rw-r--r--.  1 root root    12288 Jun 18  2019 aliases.db
    drwxr-xr-x.  2 root root      236 Jun 18  2019 alternatives
    -rw-------.  1 root root      541 Mar 31  2016 anacrontab
    -rw-r--r--.  1 root root       55 Nov  4  2016 asound.conf
    -rw-r--r--.  1 root root        1 Oct 30  2018 at.deny
    drwxr-x---.  3 root root       43 Jun 18  2019 audisp
    drwxr-x---.  3 root root       83 Jun 18  2019 audit
    drwxr-xr-x.  2 root root       22 Jun 18  2019 bash_completion.d
    -rw-r--r--.  1 root root     2853 Nov  5  2016 bashrc
    drwxr-xr-x.  2 root root        6 Nov  6  2016 binfmt.d
    -rw-r--r--.  1 root root       38 Nov 29  2016 centos-release
    --More--

      在修改用户密码时,通常都需要输入两次密码以进行确认,这在编写自动化脚本时将成为一个非常致命的缺陷。通过管道符和passwd命令的--stdin参数相结合,可以用一条命令来完成密码重置的操作:

    [root@localhost ~]# echo "123456" | passwd --stdin root     //一条命令修改root用户密码
    Changing password for user root.
    passwd: all authentication tokens updated successfully.
    [root@localhost ~]# 

       通过重定向技术能够一次性地把多行信息打包输入或输出,比如让用户一直输入内容,直到用户输入了其自定义的分界符时,才结束输入。这种方法在编写自动化脚本时经常用到。

    [root@localhost ~]# mail -s "readme" root@localhost << over     //"over"为用户自定义地分界符
    > i think linux is very practical
    > i hope to learn more
    > can you teach me?
    > over               //遇到分界符后结束输入,以上3行信息则为用户输入的有效内容
    [root@localhost ~]#

    三、命令行的通配符


      通配符,顾名思义,就是通用的匹配信息的符号,常见的通配符如下所示:

      •   星号(*)代表匹配零个或多个字符;
      •   问号(?)代表匹配单个字符;
      •   中括号内加上数字([0-9])代表匹配0~9之间的单个数字的字符;
      •   中括号内加上字母([abc])则代表匹配a、b、c三个字中的任意一个字符。

      匹配在/dev目录中所有以sda开头的文件:

    [root@localhost ~]# ls -l /dev/sda*
    brw-rw----. 1 root disk 8, 0 Feb 20 23:57 /dev/sda
    brw-rw----. 1 root disk 8, 1 Feb 20 23:57 /dev/sda1
    brw-rw----. 1 root disk 8, 2 Feb 20 23:57 /dev/sda2
    [root@localhost ~]# 

      匹配以sda开头,且后面还紧跟某一个字符(字符包括字母、数字、特殊符号等等)的文件:

    [root@localhost ~]# ls -l /dev/sda?       //该命令排除了/dev/sda文件,因为不匹配空值
    -rw-r--r--. 1 root root    0 Feb 21 02:39 /dev/sda@      //该文件为本人所创建,用来实验测试
    brw-rw----. 1 root disk 8, 1 Feb 20 23:57 /dev/sda1
    brw-rw----. 1 root disk 8, 2 Feb 20 23:57 /dev/sda2
    [root@localhost ~]# 

      匹配以sda开头,且后面还紧跟某一个数字的文件:

    [root@localhost ~]# ls -l /dev/sda[0-9]
    brw-rw----. 1 root disk 8, 1 Feb 20 23:57 /dev/sda1
    brw-rw----. 1 root disk 8, 2 Feb 20 23:57 /dev/sda2
    [root@localhost ~]# 

      匹配以sda开头,且后面还紧跟1、3、5中的某一个数字的文件:

    [root@localhost ~]# ls -l /dev/sda[135]       //最好写成[1,3,5],因为这种写法更规范
    brw-rw----. 1 root disk 8, 1 Feb 20 23:57 /dev/sda1
    [root@localhost ~]# 

     四、常用的转义字符


      Shell解释器提供了丰富的转义字符来处理输入的特殊数据,常见的4个转义字符如下所示:

      •   反斜杠():使反斜杠后面的一个变量变为单纯的字符串;
      •   单引号(''):转义其中所有的变量为单纯的字符串;
      •   双引号(""):保留其中的变量属性,不进行转义处理
      •   反引号(``):把其中的命令执行后返回结果。

      实验:先定义一个名为PRICE的变量并赋值5,然后输出以双引号括起来的字符串与变量信息:

    [root@localhost ~]# PRICE=5
    [root@localhost ~]# 
    [root@localhost ~]# echo "Price is $PRICE"     //保留其中变量属性
    Price is 5     

      实验:想要输出“Price is $5”,需要使用反斜杠进行转义。

    [root@localhost ~]# echo "Price is $$PRICE"    //$$的作用是显示当前程序的进程ID号码
    Price is 2571PRICE 
    [root@localhost ~]# 
    [root@localhost ~]# echo "Price is $$PRICE"    //使用反斜杠进行转义
    Price is $5
    [root@localhost ~]# 

      实验:输出命令执行的结果。

    [root@localhost ~]# echo `uname -a`     //先执行uname -a命令,然后输出执行结果
    Linux localhost.localdomain 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
    [root@localhost ~]# 

    五、重要的环境变量


      变量是计算机系统用于保存可变值的数据类型。在Linux系统中,变量名称一般都用大写表示,这是一种约定俗成的规范。可以直接通过变量名称来提取对应的变量值。Linux系统中的环境变量是用来定义系统运行环境的一些参数,比如每个用户的家目录、邮件存放的位置等。

      在执行了一条命令后,Linux系统中到底发生了什么呢?简单来说,主要分为4个步骤:

      第1步:判断用户是否以绝对路径相对路径的方式输入命令(如/bin/ls就是以绝对路径的方式执行命令),如果是的话则直接执行。

       第2步:Linux系统检查用户输入的命令是否为“别名命名”,即用一个自定义的命令名称来替换原本的命令名称。alias命令可以用来创建属于自己的命令别名,格式为“alias 别名=命令”。unalias命令用来取消命令别名,格式为“unalias 别名”。在上图中,输入ls命令后,不同的文件类型显示不同的颜色,这其实就是Linux系统为了方便用户区分文件类型而特意设置的ls命令别名。

    [root@localhost ~]# alias ls='ls --color=auto'    //设置命令的别名,执行ls命令则等同于执行ls --cloar=auto
    [root@localhost ~]# 

       第3步:Bash解释器判断用户输入的是内部命令还是外部命令。内部命令是解释器内部的命令,会被直接执行。而用户在绝大多数输入的是外部命令,这些外部命令交由第4步处理。可以用“tyep 命令名称”来判断输入的命令是内部命令还是外部命令,能定位到命令存放的路径的都是外部命令。

    [root@linuxprobe ~]# type cat
    cat is /usr/bin/cat
    [root@linuxprobe ~]# type more
    more is /usr/bin/more

       第4步:系统在多个路径中查找用户输入的命令文件,而定义这些路径的变量叫作PATH,作用是告诉Bash解释器将要执行的命令可能存放的位置,然后Bash解释器就会乖乖地在这些路径下逐个查找。PATH变量包含多个路径值,每个路径值之间用冒号间隔,对这些路径的增加和删除操作将影响到Bash解释器对Linux命令的查找。

    [root@linuxprobe ~]# echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin   
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# PATH=$PATH:/root/bin    //添加新的路径,不过系统重启后失效
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin     //添加成功
    [root@linuxprobe ~]# 

      综上所述,作为一名态度谨慎的运维工作者来说,在接手一台新的Linux系统后一定要检查PATH变量中是否有可疑的目录。另外,可以使用env命令来查看Linux系统中所有的环境变量,其中最重要的10个环境变量如下所示:

    变量名称 作用
    HOME 用户的主目录(即家目录)
    SHELL 用户当前使用的SHELL解释器的名称
    HISTSIZE 输出的历史命令记录条数
    HISTFILESIZE 保存的历史命令记录条数
    MAIL 邮件保存路径
    LANG 系统语言、语系名称(出现乱码后,首先检查该变量)
    RANDOM 生成一个随机数字
    PS1 Bash解释器的提示符
    PATH 定义解释器搜索用户执行命令的路径
    EDITOR 用户默认的文本编辑器

      Linux作为一个多用户多任务的操作系统,能够为每个用户提供独立的、合适的工作运行环境,因此,一个相同的变量会因为用户身份的不同而具有不同的值。

    [root@linuxprobe ~]# echo $HOME
    /root
    [root@linuxprobe ~]# su - linuxprobe      //切换至linuxprobe用户
    Last login: Sat Feb 15 19:28:26 BNT 2020 on :0
    [linuxprobe@linuxprobe ~]$ 
    [linuxprobe@linuxprobe ~]$ echo $HOME
    /home/linuxprobe
    [linuxprobe@linuxprobe ~]$ 

      我们完全可以自行创建一个变量,来满足工作需求。例如设置一个名为WORKDIR的变量,如下所示:

    [root@linuxprobe ~]# mkdir /home/workdir    //新建一个目录
    [root@linuxprobe ~]#   
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# WORKDIR=/home/workdir  //新建一个变量,并将路径赋值给WORKDIR变量
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# cd $WORKDIR
    [root@linuxprobe workdir]# pwd
    /home/workdir
    [root@linuxprobe workdir]# 

      这样的变量不具有全局性,作用范围有限,可以使用export命令将其提升为全局变量,这样其他用户就可以使用了。注意:当使用su - 命令切换用户时,export命令无效

    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# WORKDIR=/home/workdir/    //给WORKDIR变量赋值
    [root@linuxprobe ~]# echo $WORKDIR
    /home/workdir/
    [root@linuxprobe ~]# export WORKDIR    //提升为全局变量
    [root@linuxprobe ~]# 
    [root@linuxprobe ~]# su linuxprobe   //切换至linuxprobe用户
    [linuxprobe@linuxprobe root]$ 
    [linuxprobe@linuxprobe root]$ echo $WORKDIR     //成功输出WORKDIR变量的值
    /home/workdir/           
    [linuxprobe@linuxprobe root]$ su - linuxprobe   //使用su -命令切换至linuxprobe用户
    Password: 
    Last login: Sat Feb 22 11:52:23 BNT 2020 on pts/0
    [linuxprobe@linuxprobe ~]$ echo $WORKDIR     //无法查看WORKDIR变量的值
    
    [linuxprobe@linuxprobe ~]$ 

     

  • 相关阅读:
    "#"
    网络请求
    iOS_正则表达式判断手机型号、邮箱、手机号、身份证、昵称、密码等
    程序员
    js交互
    android 性能优化
    Android 开源的项目框架
    Android 开源框架案例
    Android Listview上拉刷新加载框架
    android 上传文件到服务器FIP
  • 原文地址:https://www.cnblogs.com/xuliang-daydayup/p/12337711.html
Copyright © 2011-2022 走看看