輸入輸出重定向
??輸入重定向是指把文件導(dǎo)入到命令中,而輸出重定向則是把原本要輸出到屏幕的數(shù)據(jù)信息寫入到指定文件中.
? 標(biāo)準(zhǔn)輸入重定向(STDIN,文件描述符為0):默認(rèn)從鍵盤輸入,也可從其他文件或命令中輸入.
? 標(biāo)準(zhǔn)輸出重定向(STDOUT,文件描述符為1):默認(rèn)輸出到屏幕
? 錯(cuò)誤輸出重定向(STDERR,文件描述符為2):默認(rèn)輸出到屏幕
??對于輸入重定向來講,用到的符號(hào)及其作用如表 3-1 所示。
??????????????表3-1 ???? 輸入重定向中用到的符號(hào)及其作用
| 符號(hào) | 作用 |
|---|---|
| 命令 < 文件 | 將文件作為命令的標(biāo)準(zhǔn)輸入 |
| 命令 <<分界符 | 從標(biāo)準(zhǔn)輸入中讀入,直到遇見分界符才停止 |
| 命令 <文件1> 文件2 | 將文件1作為命令的標(biāo)準(zhǔn)輸入并將標(biāo)準(zhǔn)輸出到文件2 |
??對于輸出重定向來講,用到的符號(hào)及其作用如表3-2所示例.
??????????????表3-2 ????輸出重定向中用到的符號(hào)及其作用
| 符號(hào) | 作用 |
|---|---|
| 命令 > 文件 | 將標(biāo)準(zhǔn)輸出重定向到一個(gè)文件中(清空原有文件的數(shù)據(jù)) |
| 命令 2> 文件 | 將錯(cuò)誤輸出重定向到一個(gè)文件中(清空原有文件的數(shù)據(jù)) |
| 命令 >> 文件 | 將標(biāo)準(zhǔn)輸出重定向到一個(gè)文件中(追加到原有內(nèi)容的后面) |
| 命令 2>> 文件 | 將錯(cuò)誤輸出重定向到一個(gè)文件中(追加到原有內(nèi)容的后面) |
| 命令 >> 文件 2>&1 或 命令 &>> 文件 | 將標(biāo)準(zhǔn)輸出與錯(cuò)誤輸出共同寫入到文件中(追加到原有內(nèi)容的后面) |
??通過標(biāo)準(zhǔn)輸出重定向?qū)an bash命令原本要輸出到屏幕的信息寫入到文件readme.txt中,然后顯示readme.txt文件中的內(nèi)容:
[root@linuxprobe ~]# man bash > readme.txt
[root@linuxprobe ~]# cat readme.txt
BASH(1)
General Commands Manual
NAME
bash - GNU Bourne-Again SHell
SYNOPSIS
bash [options] [file]
COPYRIGHT
Bash is Copyright (C) 1989-2011 by the Free Software Foundation, Inc.
DESCRIPTION
Bash is an sh-compatible command language interpreter that executes
commands read from the standard input or from a file. Bash also incor‐
porates useful features from the Korn and C shells (ksh and csh).
Bash is intended to be a conformant implementation of the Shell and
Utilities portion of the IEEE POSIX specification (IEEE Standard
1003.1). Bash can be configured to be POSIX-conformant by default.
..................省略部分輸出信息..................
??輸出重定向技術(shù)中的覆蓋寫入與追加寫入:首先通過覆蓋寫入模式向readme.txt文件寫入一行數(shù)據(jù)(該文件中包含了上一個(gè)實(shí)驗(yàn)的man 命令信息),然后再通過追加寫入模式向文件再寫入一次數(shù)據(jù),其命令如下:
[root@linuxprobe ~]# echo "Welcome to LinuxProbe.Com" > readme.txt
[root@linuxprobe ~]# echo "Quality linux learning materials" >> readme.txt
??在執(zhí)行 cat 命令之后,可以看到如下所示的文件內(nèi)容:
[root@linuxprobe ~]# cat readme.txt
Welcome to LinuxProbe.Com
Quality linux learning materials
??不同命令的標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出還是有區(qū)別的:
zheng@zheng-Vostro-3667:~/下載$ ls -l xx
ls: 無法訪問'xx': 沒有那個(gè)文件或目錄
zheng@zheng-Vostro-3667:~/下載$ ls -l xx > readme.txt
ls: 無法訪問'xx': 沒有那個(gè)文件或目錄
zheng@zheng-Vostro-3667:~/下載$ cat readme.txt
zheng@zheng-Vostro-3667:~/下載$ ls -l xx 2> readme.txt
zheng@zheng-Vostro-3667:~/下載$ cat readme.txt
ls: 無法訪問'xx': 沒有那個(gè)文件或目錄
zheng@zheng-Vostro-3667:~/下載$
管道命令符
??同時(shí)按下鍵盤上的Shift+\鍵即可輸入管道符,其執(zhí)行格式為 "命令A(yù)|命令B".管道命令符的作用也可以用一句話來概括"把前一個(gè)命令原本要輸出到屏幕的標(biāo)準(zhǔn)正常數(shù)據(jù)當(dāng)作是后一個(gè)命令的標(biāo)準(zhǔn)輸入".
??例如,我們可以把兩條命令合并為一條:
? 找出被限制登錄用戶的命令是 grep "/sbin/nologin" /etc/passwd
? 統(tǒng)計(jì)文本行數(shù)的命令則是wc -l
zheng@zheng-Vostro-3667:~/go/src/gitlab.fz.stevegame.red/back-end/room/log$ grep /sbin/nologin /etc/passwd |wc -l
34
??我們可以將它套用到其他不同的命令上,比如用翻頁的形式查看/etc目錄中的文件列表及屬性信息(這些內(nèi)容默認(rèn)會(huì)一股腦兒地顯示到屏幕上,根本看不清除):
zheng@zheng-Vostro-3667:~/go/src/gitlab.fz.stevegame.red/back-end/room/log$ ls -l /etc/ |more
總用量 1172
drwxr-xr-x 3 root root 4096 7月 25 2018 acpi
-rw-r--r-- 1 root root 3028 7月 25 2018 adduser.conf
drwxr-xr-x 2 root root 4096 7月 31 2018 alternatives
-rw-r--r-- 1 root root 401 5月 30 2017 anacrontab
drwxr-xr-x 3 root root 4096 7月 28 2018 apache2
-rw-r--r-- 1 root root 433 10月 2 2017 apg.conf
drwxr-xr-x 6 root root 4096 7月 25 2018 apm
drwxr-xr-x 3 root root 4096 10月 6 06:31 apparmor
drwxr-xr-x 8 root root 4096 2月 14 06:12 apparmor.d
drwxr-xr-x 4 root root 4096 10月 23 10:00 apport
-rw-r--r-- 1 root root 769 4月 4 2018 appstream.conf
drwxr-xr-x 6 root root 4096 2月 12 14:35 apt
drwxr-xr-x 3 root root 4096 2月 1 06:01 avahi
--更多--
命令行的通配符
??假設(shè)想要批量查看所有硬盤文件的相關(guān)權(quán)限屬性,一種方式是這樣的:
root@zheng-Vostro-3667:/home/zheng/go/src/gitlab.fz.stevegame.red/back-end/room/log# ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 2月 18 14:15 /dev/sda
root@zheng-Vostro-3667:/home/zheng/go/src/gitlab.fz.stevegame.red/back-end/room/log# ls -l /dev/sda1
brw-rw---- 1 root disk 8, 1 2月 18 14:15 /dev/sda1
root@zheng-Vostro-3667:/home/zheng/go/src/gitlab.fz.stevegame.red/back-end/room/log# ls -l /dev/sda2
brw-rw---- 1 root disk 8, 2 2月 18 14:15 /dev/sda2
root@zheng-Vostro-3667:/home/zheng/go/src/gitlab.fz.stevegame.red/back-end/room/log# ls -l /dev/sda3
ls: 無法訪問'/dev/sda3': 沒有那個(gè)文件或目錄
??這些硬盤設(shè)備文件都是以sda開頭并且存放到了/dev目錄中,這樣一來,即使我們不知道硬盤的分區(qū)編號(hào)和具體分區(qū)的個(gè)數(shù),也可以使用通配符來搞定.
??通配符就是通用的匹配信息的符號(hào),比如 * 代表匹配零個(gè)或多個(gè)字符, ?代表匹配單個(gè)字符,中括號(hào)內(nèi)加上數(shù)字[0-9]代表匹配 0~9 之間的單個(gè)數(shù)字的字符,而中括號(hào)內(nèi)加上字母[abc]則是代表匹配a、b、c三個(gè)字符中的任意一個(gè)字符
??例如,下面來匹配所有在/dev目錄中且以sda開頭的文件:
root@zheng-Vostro-3667:/home/zheng/go/src/gitlab.fz.stevegame.red/back-end/room/log# ls -l /dev/sda*
brw-rw---- 1 root disk 8, 0 2月 18 14:15 /dev/sda
brw-rw---- 1 root disk 8, 1 2月 18 14:15 /dev/sda1
brw-rw---- 1 root disk 8, 2 2月 18 14:15 /dev/sda2
brw-rw---- 1 root disk 8, 5 2月 18 14:15 /dev/sda5
root@zheng-Vostro-3667:/home/zheng/go/src/gitlab.fz.stevegame.red/back-end/room/log# ls -l /dev/sda?
brw-rw---- 1 root disk 8, 1 2月 18 14:15 /dev/sda1
brw-rw---- 1 root disk 8, 2 2月 18 14:15 /dev/sda2
brw-rw---- 1 root disk 8, 5 2月 18 14:15 /dev/sda5
root@zheng-Vostro-3667:/home/zheng/go/src/gitlab.fz.stevegame.red/back-end/room/log# ls -l /dev/sda[0-9]
brw-rw---- 1 root disk 8, 1 2月 18 14:15 /dev/sda1
brw-rw---- 1 root disk 8, 2 2月 18 14:15 /dev/sda2
brw-rw---- 1 root disk 8, 5 2月 18 14:15 /dev/sda5
常用的轉(zhuǎn)義字符
??4個(gè)最常用的轉(zhuǎn)義字符如下所示
?反斜杠 \ :使反斜杠后面的一個(gè)變量變?yōu)閱渭兊淖址?
?單引號(hào) '': 轉(zhuǎn)義其中所有的變量為單純的字符串
?雙引號(hào) "": 保留其中的變量屬性,不進(jìn)行轉(zhuǎn)義處理
?反引號(hào) ``:把其中的命令執(zhí)行后返回
??先定義一個(gè)名為PRICE的變量并賦值為5,然后輸出雙引號(hào)括起來的字符串與變量信息:
zheng@zheng-Vostro-3667:~$ PRICE=5
zheng@zheng-Vostro-3667:~$ echo "Price is $PRICE"
Price is 5
zheng@zheng-Vostro-3667:~$ echo "PRICE"
PRICE
??如果我們希望輸出"Price is $5",$$作用是顯示當(dāng)前程序的進(jìn)程ID號(hào)碼,那么就需要使用反斜杠( \ )來進(jìn)行轉(zhuǎn)義,將這個(gè)命令提取符轉(zhuǎn)義成單純的文本,去除其特殊功能.
zheng@zheng-Vostro-3667:~$ echo "Price is $$PRICE"
Price is 27790PRICE
zheng@zheng-Vostro-3667:~$ echo "Price is \$$PRICE"
Price is $5
zheng@zheng-Vostro-3667:~$
??如果只需要某個(gè)命令的輸出值時(shí),可以像`命令`這樣,將命令用反引號(hào)括起來,達(dá)到預(yù)期的效果.例如,將反引號(hào)與 uname-a 命令結(jié)合, 然后使用echo 命令來查看本機(jī)的Liunx版本和內(nèi)核信息:
zheng@zheng-Vostro-3667:~$ echo `uname -a`
Linux zheng-Vostro-3667 4.15.0-45-generic #48-Ubuntu SMP Tue Jan 29 16:28:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
??在Liunx系統(tǒng)中一切都是文件,Liunx命令也不例外.那么,在用戶執(zhí)行了一條命令之后,Liunx系統(tǒng)中到底發(fā)生了什么事情呢?簡單來說,命令在Liunx中的執(zhí)行分為4個(gè)步驟.
第1步: 判斷用戶是否以絕對路徑或相對路徑的方式輸入命令(如 /bin/ls), 如果是的話則直接執(zhí)行.
第2步: Liunx系統(tǒng)檢查用戶輸入的命令是否是"別名命令",即用一個(gè)自定義的命令名稱來替換原本的命令名稱.可以用alias命令來創(chuàng)建一個(gè)屬于自己的命令別名,格式為"alias 別名=命令".若要取消一個(gè)命令別名,則是用unalias命令,格式為
"unalias 別名". 我們之前在使用rm命令刪除文件時(shí),Liunx系統(tǒng)都會(huì)要求我們再確認(rèn)是否執(zhí)行刪除操作,其實(shí)這就是Liunx系統(tǒng)為了防止用戶誤刪除文件而特意設(shè)置的rm別名命令,接下來我們把它取消掉:
zheng@zheng-Vostro-3667:~$ alias rm='rm -i'
zheng@zheng-Vostro-3667:~$ rm gold_change:room-127.0.0.1-13001.diskqueue.meta.dat
rm:是否刪除普通文件 'gold_change:room-127.0.0.1-13001.diskqueue.meta.dat'? ^C
zheng@zheng-Vostro-3667:~$ unalias rm
zheng@zheng-Vostro-3667:~$ rm gold_change:room-127.0.0.1-13001.diskqueue.meta.dat
第3步:Bash解釋器判斷用戶輸入的是內(nèi)部命令還是外部命令.內(nèi)部命令是解釋器內(nèi)部的指令,會(huì)被直接執(zhí)行;而用戶在絕大部分時(shí)間輸入的是外部命令,這些命令交由步驟4繼續(xù)處理.可以使用"type 命令名稱"來判斷用戶輸入的命令是內(nèi)部命令還是外部命令
zheng@zheng-Vostro-3667:~$ type rm
rm 已被錄入哈希表 (/bin/rm)
zheng@zheng-Vostro-3667:~$ type ls
ls 是 `ls --color=auto' 的別名
zheng@zheng-Vostro-3667:~$ type cat
cat 是 /bin/cat
zheng@zheng-Vostro-3667:~$ type cd
cd 是 shell 內(nèi)建
zheng@zheng-Vostro-3667:~$ type grep
grep 是 `grep --color=auto' 的別名
第4步:系統(tǒng)在多個(gè)路徑中查找用戶輸入的命令文件,而定義這些路徑的變量叫做PATH,可以簡單地把它理解成是"解釋器的小助手",作用是告訴Bash解釋器執(zhí)行的命令可能存放的位置,每個(gè)路徑值之間用冒號(hào)間隔,對這些路徑的增加和刪除操作將影響到Bash解釋器對Liunx命令的查找.
zheng@zheng-Vostro-3667:~$ echo $PATH
/home/zheng/.local/bin:/home/zheng/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/zheng/go/bin:=/home/zheng/go/bin:/home/zheng/software/go1.10.3.linux-amd64/go/bin:/home/zheng/software/nsq-1.0.0-compat.linux-amd64.go1.8/bin
zheng@zheng-Vostro-3667:~$ PATH=$PATH:/zheng
zheng@zheng-Vostro-3667:~$ echo $PATH
/home/zheng/.local/bin:/home/zheng/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/zheng/go/bin:=/home/zheng/go/bin:/home/zheng/software/go1.10.3.linux-amd64/go/bin:/home/zheng/software/nsq-1.0.0-compat.linux-amd64.go1.8/bin:/zheng
我們可以用env命令來查看到Liunx系統(tǒng)中的所有環(huán)境變量
表 3-3 Linux 系統(tǒng)中最重要的 10 個(gè)環(huán)境變量
| 變量命令 | 作用 |
|---|---|
| HOME | 用戶的主目錄(即家目錄) |
| SHELL | 用戶在使用的 Shell 解釋器名稱 |
| HISTSIZE | 輸出的歷史命令記錄條數(shù) |
| HISTFILESIZE | 保存的歷史命令記錄條數(shù) |
| 郵件保存路徑 | |
| LANG | 系統(tǒng)語言、語系名稱 |
| RANDOM | 生成一個(gè)隨機(jī)數(shù)字 |
| PS1 | Bash 解釋器的提示符 |
| PATH | 定義解釋器搜索用戶執(zhí)行命令的路徑 |
| EDITOR | 用戶默認(rèn)的文本編輯器 |
??Liunx作為一個(gè)多用戶多任務(wù)的操作系統(tǒng),能夠?yàn)槎鄠€(gè)用戶提供獨(dú)立的、合適的工作運(yùn)行環(huán)境,因此,一個(gè)相同的變量會(huì)因?yàn)橛脩羯矸莸牟煌哂胁煌闹?例如,我們使用下述命令來查看HOME變量在不同用戶身份下都有哪些值:
zheng@zheng-Vostro-3667:~$ echo $HOME
/home/zheng
zheng@zheng-Vostro-3667:~$ su - root
密碼:
root@zheng-Vostro-3667:~# echo $HOME
/root
root@zheng-Vostro-3667:~#
??其實(shí)變量是由固定的變量名與用戶或系統(tǒng)設(shè)置的變量值兩部分組成,我們完全可以自行創(chuàng)建變量,來滿足工作需求.例如設(shè)置一個(gè)名稱為WORKDIR的變量,方便用戶更輕松地進(jìn)入一個(gè)層次較深的目錄:
zheng@zheng-Vostro-3667:~$ sudo rm -rf /home/workdir
zheng@zheng-Vostro-3667:~$ sudo mkdir /home/workdir
zheng@zheng-Vostro-3667:~$ WORKDIR=/home/workdir
zheng@zheng-Vostro-3667:~$ echo $WORKDIR
/home/workdir
zheng@zheng-Vostro-3667:~$ sudo rm -rf /home/workdir
zheng@zheng-Vostro-3667:~$ echo $WORKDIR
/home/workdir
zheng@zheng-Vostro-3667:~$
??但是這樣的變量不具有全局性,作用范圍也有限,默認(rèn)情況下不能被其他用戶使用,如果工作需要,可以使用export命令將其提升為全局變量,這樣其他用戶也就可以使用它了:
[root@linuxprobe workdir]# su linuxprobe
Last login: Fri Mar 20 20:52:10 CST 2017 on pts/0
[linuxprobe@linuxprobe ~]$ cd $WORKDIR
[linuxprobe@linuxprobe ~]$ echo $WORKDIR
[linuxprobe@linuxprobe ~]$ exit
[root@linuxprobe ~]# export WORKDIR
[root@linuxprobe ~]# su linuxprobe
Last login: Fri Mar 20 21:52:10 CST 2017 on pts/0
[linuxprobe@linuxprobe ~]$ cd $WORKDIR
[linuxprobe@linuxprobe workdir]$ pwd
/home/workdir