输入输出重定向

输入重定向是把文件导入到命令中,而输出重定向则是把原本要输出到屏幕上的数据信息写入到指定文件中。在日常的学习和工作中,相较于输入重定向,我们使用输出重定向的频率更高,所以又将输出重定向分为标准输出重定向和错误输出重定向两种不同的技术,以及清空写入与追加写入两种模式。

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

我们分别查看两个文件的属性信息,其中第二个文件是不存在的,虽然针对这两个文件的操作都分别会在屏幕上输出一些数据信息,但这两个操作的差异其实很大:

root@ubuntu-1:~/workroom/c_test/test_dir$ touch test
root@ubuntu-1:~/workroom/c_test/test_dir$ ls
test
root@ubuntu-1:~/workroom/c_test/test_dir$
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l test
-rw-rw-r-- 1 root root 0 Aug 24 23:32 test
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l xxx
ls: cannot access 'xxx': No such file or directory

在上述命令中,名为test的文件是存在的,输出信息是该文件的一些相关权限,所有者,所属组,文件大小及修改时间等信息,这也是该命令的标准输出信息。而名为xxx的第二个文件是不存在的,因此在执行ls命令之后显示的报错信息也是该命令的错误输出信息。要想把原本输出到屏幕上的数据转而写入到文件当中,就要区别对待这两种输出信息了。

对于输入重定向来讲,用到的符号及其作用:

符号

作用

命令 < 文件

将文件作为命令的标准输入

命令 文件2

将文件1作为命令的标准输入并将标准输出到文件2

对于输入重定向来讲,用到的符号及其作用:

符号

作用

命令 > 文件

将标准输出重定向到一个文件中,清空原有文件的数据。

命令2 > 文件

将错误输出重定向到一个文件中,清空原有文件的数据。

命令 >> 文件

将标准输出重定向到一个文件中,追加到原有内容的后面。

命令 2>> 文件

将错误输出重定向到一个文件中,追加到原有内容的后面。

命令 >> 文件 2>&1 或命令 &>> 文件

将标准输出与错误输出共同写入到文件中,追加到原有内容的后面。

对于重定向的标准输出模式,可以省略文件描述符1不写,而错误输出模式的文件描述符2是必须要写的。

root@ubuntu-1:~/workroom/c_test/test_dir$ man strcpy > readme.txt
root@ubuntu-1:~/workroom/c_test/test_dir$ ls
readme.txt  test
root@ubuntu-1:~/workroom/c_test/test_dir$ cat readme.txt
STRCPY(3)                                   Linux Programmer's Manual                                   STRCPY(3)
NAME
       strcpy, strncpy - copy a string
SYNOPSIS
       #include 
       char *strcpy(char *dest, const char *src);
       char *strncpy(char *dest, const char *src, size_t n);
DESCRIPTION
       The  strcpy() function copies the string pointed to by src, including the terminating null byte (''), to
       the buffer pointed to by dest.  The strings may not overlap, and the destination string dest must be large
       enough to receive the copy.  Beware of buffer overruns!  (See BUGS.)

接下来尝试输出重定向技术中的覆盖写入与追加这两种不同模式带来的变化。首先通过覆盖写入模式向.txt文件写入一行数据(该文件中包含上一个实验的man命令信息),然后再通过追加写入模式向文件再写入一次数据,其命令如下:

root@ubuntu-1:~/workroom/c_test/test_dir$ echo "Welcome to Linux" > readme.txt
root@ubuntu-1:~/workroom/c_test/test_dir$ echo "Learning Linux" >> readme.txt
root@ubuntu-1:~/workroom/c_test/test_dir$ cat readme.txt
Welcome to Linux
Learning Linux

虽然都是输出重定向技术,但是不同命令的标准输出和错误输出还是有区别的。例如查看当前目录中某个文件的信息,这个以test文件为例,因为这个文件是真实存在的,因此使用标准输出即可将原本要输出到屏幕的信息写入到文件中,而错误的输出重定向则依然把信息输出到了屏幕上。

root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l test
-rw-rw-r-- 1 chengy chengy 0 Aug 24 23:32 test
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l test > stderr.txt
root@ubuntu-1:~/workroom/c_test/test_dir$ cat stderr.txt
-rw-rw-r-- 1 root root 0 Aug 24 23:32 test
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l test 2> stderr.txt
-rw-rw-r-- 1 root root 0 Aug 24 23:32 test

如果想把命令的报错信息写入到文件,该怎么操作呢?当用户在执行一个自动化的Shell脚本时,这个操作会特别有用,而且特别实用,因为它可以把整个脚本执行过程中的报错信息都记录到文件中,便于安装后的排错工作。

root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l xxx
ls: cannot access 'xxx': No such file or directory
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l xxx > stderr.txt
ls: cannot access 'xxx': No such file or directory
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l xxx 2> stderr.txt
root@ubuntu-1:~/workroom/c_test/test_dir$ cat stderr.txt
ls: cannot access 'xxx': No such file or directory

接下来使用输入重定向把.txt文件导入wc -l 命令,统计一下文件中的内容行数。

root@ubuntu-1:~/workroom/c_test/test_dir$ wc -l < readme.txt
2

root@ubuntu-1:~/workroom/c_test/test_dir$ cat readme.txt | wc -l
2

管道命令符

管道命令符的作用是把前一个命令原本要输出到屏幕的正常数据当作是后一个命令的标准输入。

通过匹配关键词/sbin/找出了所有被限制登录系统的用户。

找出被限制登录用户的命令是grep "/sbin/nologin" /etc/passwd;
统计文本行数的命令是wc -l;

现在要做的就是把搜索命令的输出值传递给统计命令,即把原本要输出到屏幕的用户信息列表再交给wc命令作进一步的加工,因此只需要把管道符放到两条命令之间即可。

root@ubuntu-1:~/workroom/c_test/test_dir$ grep "/sbin/nologin" /etc/passwd | wc -l
17

我们可以将它套用到其它不同的命令上,比如用翻页的形式查看/etc目录中的文件列表及属性信息:

strncpy函数用法_strncpy_strncpy会补0吗

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

# echo "test" | passwd --stdin root
Changing password for user root.
passwd: all authentication tokens updated successfully.

当然,大家千万不要误以为管道命令符只能在一个命令组合中使用一次,我们完全可以这样使用:”命令A | 命令B | 命令C”。

命令行的通配符

假设想要批量查看所有硬件文件的相关权限属性,一种方式是这样的:

root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda
sda   sda1  sda2  sda5
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 Aug 18 23:42 /dev/sda
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda1
brw-rw---- 1 root disk 8, 1 Aug 18 23:42 /dev/sda1
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda2
brw-rw---- 1 root disk 8, 2 Aug 18 23:42 /dev/sda2
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda5
brw-rw---- 1 root disk 8, 5 Aug 18 23:42 /dev/sda5
root@ubuntu-1:~/workroom/c_test/test_dir$

通配符就是通用的匹配信息的符号,比如星号(*)代表匹配零个或多个字符,问号(?)代表匹配单个字符,中括号内加上数字[0-9]代表匹配0~9之间的单个数字的字符,而中括号内加上字母[abc]则是代表匹配a,b,c三个字符中的任意一个字符。

下面我们就来匹配所有在/dev目录中且以sda开头的文件:

root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda*
brw-rw---- 1 root disk 8, 0 Aug 18 23:42 /dev/sda
brw-rw---- 1 root disk 8, 1 Aug 18 23:42 /dev/sda1
brw-rw---- 1 root disk 8, 2 Aug 18 23:42 /dev/sda2
brw-rw---- 1 root disk 8, 5 Aug 18 23:42 /dev/sda5

如果只想查看文件名为sda开头,但是后面还紧跟其它某一个字符的文件的相关信息,就需要用到问号来进行通配了

root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda?
brw-rw---- 1 root disk 8, 1 Aug 18 23:42 /dev/sda1
brw-rw---- 1 root disk 8, 2 Aug 18 23:42 /dev/sda2
brw-rw---- 1 root disk 8, 5 Aug 18 23:42 /dev/sda5

使用[0-9] 来匹配0~9之间的单个数字,也可以用[135]这样的方式仅匹配这三个指定数字中的一个,若没有匹配到,则不会显示出来:

root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda[0-9]
brw-rw---- 1 root disk 8, 1 Aug 18 23:42 /dev/sda1
brw-rw---- 1 root disk 8, 2 Aug 18 23:42 /dev/sda2
brw-rw---- 1 root disk 8, 5 Aug 18 23:42 /dev/sda5
root@ubuntu-1:~/workroom/c_test/test_dir$ ls -l /dev/sda[135]
brw-rw---- 1 root disk 8, 1 Aug 18 23:42 /dev/sda1
brw-rw---- 1 root disk 8, 5 Aug 18 23:42 /dev/sda5

常用的转义字符

常用的转义字符如下所示:

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

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

root@ubuntu-1:~/workroom/c_test/test_dir$ PRI=3
root@ubuntu-1:~/workroom/c_test/test_dir$ echo "pri is $PRI"
pri is 3

接下来,我们希望能够输出”pri is $3″, 要想让第一个”#34;作为符号输出,那么就需要使用反斜杠()来进行转义,将这个命令提取符转义成单纯的文本,去除其特殊功能。

root@ubuntu-1:~/workroom/c_test/test_dir$ echo "pri is $PRI"
pri is 24924PRI

root@ubuntu-1:~/workroom/c_test/test_dir$ PRI=6
root@ubuntu-1:~/workroom/c_test/test_dir$ echo "pri is $PRI"
pri is $6

而如果只需要某个命令的输出值时,可以像命令这样,将命令用反引号括起来,达到预期的效果。例如,将反引号与uname -a命令结合,然后使用echo命令来查看本机的Liunx版本和内核信息:

root@ubuntu-1:~/workroom/c_test/test_dir$ echo `uname -a`
Linux ubuntu-1 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

重要的环境变量

为了通过环境变量帮助Linux系统构建为用户提供服务的工作运行环境,需要数百个变量协同工作才能完成。简单来说,命令在Linux中的执行分为4个步鄹:

root@ubuntu-1:~/workroom/c_test/test_dir$ alias rm
alias rm='rm -fr '
root@ubuntu-1:~/workroom/c_test/test_dir$ ls
readme.txt  stderr.txt  test
chengy@ubuntu-1:~/workroom/c_test/test_dir$ rm -i test
rm: remove regular empty file 'test'? n
chengy@ubuntu-1:~/workroom/c_test/test_dir$ ls
readme.txt  stderr.txt  test

root@ubuntu-1:~/workroom/c_test/test_dir$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/otn_toolchain/toolchain/host/usr/bin:/opt/toolchain/aarch64/bin

Linux 系统中最重要的几个环境变量

变量名称

作用

HOME

用户的主目录

SHELL

用户在使用的Shell 解释器名称

输出的历史命令记录条数

保存的历史命令记录条数

MAIL

邮件保存路径

LANG

系统语言,语系名称

生成一个随机数字

PS1

Bash解释器的提示符

PATH

定义解释器搜索用户执行命令的路径

用户默认的文本编辑器

root@ubuntu-1:~/workroom/c_test/test_dir$ echo $RANDOM
28773
root@ubuntu-1:~/workroom/c_test/test_dir$ echo $EDITOR
root@ubuntu-1:~/workroom/c_test/test_dir$ echo $PS1
[e]0;u@h: wa]${debian_chroot:+($debian_chroot)}[33[01;32m]u@h[33[00m]:[33[01;34m]w[33[00m]$
root@ubuntu-1:~/workroom/c_test/test_dir$ echo $LANG
en_US.UTF-8
root@ubuntu-1:~/workroom/c_test/test_dir$ echo $MAIL
/var/mail/root
root@ubuntu-1:~/workroom/c_test/test_dir$ echo $HOME
/home/root
root@ubuntu-1:~/workroom/c_test/test_dir$ echo $SHELL
/bin/bash
root@ubuntu-1:~/workroom/c_test/test_dir$ echo $HISTSIZE
1000
root@ubuntu-1:~/workroom/c_test/test_dir$ echo $HISTFILESIZE
2000

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

其实变量是有固定的变量名与用户或系统设置的变量值两部分组成的,我们完全可以自行创建变量,来满足工作需求。例如设置一个名称为的变量,方便用户更轻松地进入一个层次较深的目录:

root@ubuntu-1:~/workroom/c_test/test_dir$ pwd
/home/test/workroom/c_test/test_dir
root@ubuntu-1:~/workroom/c_test/test_dir$ WORKDIR=/home/test/workroom/c_test/test_dir
root@ubuntu-1:~/workroom/c_test/test_dir$ cd $WORKDIR
root@ubuntu-1:~/workroom/c_test/test_dir$ cd ..
root@ubuntu-1:~/workroom/c_test$ cd ..
root@ubuntu-1:~/workroom$ cd $WORKDIR
root@ubuntu-1:~/workroom/c_test/test_dir$

但是,这样的变量不具有全局性,作用范围有限,默认情况下不能被其它用户使用,如果工作需要,可以使用命令将其提升为全局变量,这样其它用户也就可以使用它了。

root@ubuntu-1:~/workroom$ cd $WORKDIR
root@ubuntu-1:~/workroom/c_test/test_dir$export WORKDIR

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,永久会员只需109元,全站资源免费下载 点击查看详情
站 长 微 信: nanadh666

声明:1、本内容转载于网络,版权归原作者所有!2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!