管道与连接

管道与连接

命令连接

在 Bash 下,您可以创建一个由以下操作符之一分隔的一个或多个命令序列:

Operator Syntax Description Example
; command1; command2 Separates commands that are executed in sequence. In this example, pwd is executed only after date command completes. date ; pwd
& command arg & The shell executes the command in the background in a subshell. The shell does not wait for the command to finish, and the return status is 0. The & operator runs the command in background while freeing up your terminal for other work. In this example, find command is executed in background while freeing up your shell prompt. find / -iname "*.pdf" >/tmp/output.txt &
&& command1 && command2 command2 is executed if, and only if, command1 returns an exit status of zero i.e. command2 only runs if first command1 run successfully. [ ! -d /backup ] && mkdir -p /backup See Logical AND section for examples.
|| command1 || command2 command2 is executed if and only if command1 returns a non-zero exit status i.e. command2 only runs if first command fails. `tar cvf /dev/st0 /home || mail -s ‘Backup failed’ you@example.com See Logical OR section for examples.
| command1 | command2 Linux shell pipes join the standard output of command1 to the standard input of command2. In this example, output of the ps command is provided as the standard input to the grep command `ps aux grep httpd`

;

您可以使用 ; 建立命令序列。字符(运算符)和语法为:

command1 ; command2 ; commandN
# OR
{ command1; command2 }

这样,您可以一个接一个地运行命令。在以下示例中,如果未传递足够的命令行参数(math.sh),shell 脚本将显示错误消息:

#!/bin/bash
a=$1
b=$3
op=$2
ans=0

# display usage
# run commands one after the other using ; chracter
[ $# -eq 0 ] && { echo -e "Usage: $0 num1 op num2\n\t $0 1 + 5";  exit 1; }

case $op in
	+)
		ans=$((( a+b )));;
	-)
		ans=$((( a-b )));;
	/)
		ans=$((( a/b )));;
	\*|x)
		ans=$((( a*b )));;
	*)
		echo "Unknown operator."
		exit 2;;
esac
echo "$a $op $b = $ans"

&&

如果使用逻辑 AND(&&)运算符成功执行 command1,请运行 command2:

command1 && command2

例如,如果存在 wget 命令则执行 echo 命令:

$ type -a wget >/dev/null && echo "wget command found. Download the Linux kernel ..."

||

类似地,仅当 foo 命令使用逻辑 OR 运算符返回非零退出状态时,才执行 bar 命令:

$ foo || bar

示例

因此,我们可以结合 bash 退出命令和退出代码来构建快速逻辑,如下所示:

$ my_command && echo "Done" || echo "Failed"
$ /usr/bin/rsnapshot daily && echo "Backup successful" || echo "Backup failed. Alerting OPS team..."
$ mkdir /opt/kernel && cd $_ && echo "Directory created and you are in $PWD"

我们还可以将某些命令合并编组:

[ -f /path/to/file ] && { echo "File found. Starting ...";
                          /path/to/command2;
                          /path/to/command3 arg1 arg2;
                        }

## another example ##
[[ "$value" != "Yes" ]] && {
                              _errs=("${_errs[@]}" "<p>The I/O thread for reading the master's binary log not found ($v: $value)</p>");
                              _is_error_found="true";
                             }

我们可以参考如下相对完整的示例:

BAK=/data2
TAPE=/dev/st0
echo "Trying to backup ${BAK} directory to tape device ${TAPE} .."

# See if $BAK directory exists or not, else die
# Set unsuccessful shell script termination with exit status # 1
[ ! -d $BAK ] && { echo "Source backup directory $BAK not found."; exit 1; }

# See if $TAPE device exists or not, else die
# Set unsuccessful shell script termination with exit status # 2
[ ! -b $TAPE ] && { echo "Backup tape drive $TAPE not found or configured."; exit 2; }

# Okay back it up
tar cvf $TAPE $BAK 2> /tmp/error.log

if [ $? -ne 0 ]
then
   # die with unsuccessful shell script termination exit status # 3
   echo "An error occurred while making a tape backup, see /tmp/error.log file".
   exit 3
fi

# Terminate our shell script with success message i.e. backup done!
exit 0

chmod +x datatapebackup.sh
./datatapebackup.sh
echo $?

成功或异常终止时,我们所有的 shell 命令都将返回退出代码。我们可以在 shell 脚本中使用 exit 命令提供退出代码。我们还学习了如何利用退出状态的功能在 Shell 脚本或命令行中构建逻辑。

管道

Shell 管道是一种将一个程序的输出连接到另一个程序的输入而无需任何临时文件的方法。

command1 | command2
command1 | command2 | commandN
command1 arg1 | command2 arg1 arg2
get_data_command | verify_data_command | process_data_command | format_data_command > output.data.file
get_data_command < input.data.file | verify_data_command | process_data_command | format_data_command > output.data.file

您可以一次连接两个或多个命令。连接两个程序的数据路径称为管道。竖线(|)是管道符号。Shell 管道更全面地支持 Unix 链接程序的哲学,以完成复杂的任务。也允许在管道中重定向。数据路径仅在一个方向上起作用:

Pipe

  • 在两个命令之间使用竖线(|)。在此示例中,将 ls 命令输出发送到 grep 命令,即确定是否有数据.txt 文件是否在当前工作目录中退出:
ls | grep "data.txt"
  • 在命令名称之后但在竖线之前列出的所有命令行参数(参数):
ls -al | grep "data.txt"
  • 无需在命令名称和竖线之间放置空格,这是可选的:
ls -al|grep "data.txt"

但是,我建议在命令名称和竖线之间使用空格,以提高可读性。您可以将管道输出重定向到文件(带有 > 符号的输出重定向):

ps aux | grep httpd > /tmp/ps.output.log
  • 暂停 ls 命令输出

Send output of the ls command as input to the more command. So that output is printed one screen full page at a time:

ls -l | more
  • 显示已登录用户的排序列表

将 who 命令的输出作为 sort 命令的输入。这样它将打印出用户的排序列表:

who | sort
who | sort > sorted_list.txt
  • 计算已登录的用户

who 命令的输出作为 wc 命令的输入给出,因此它将是登录到系统的用户数:

who | wc -l
  • 找出用户 vivek 是否登录
who | grep -i vivek
  • 计算当前目录中的文件总数
ls -l | wc  -l
  • 在给定时间执行关机命令
echo "shutdown -h now" | at 12am tomorrow
  • 挂载命令的格式输出

以良好的格式显示安装命令输出

mount | column -t
  • Backup (tar over ssh)

在安全的 ssh 会话上使用 tar 命令来备份本地 /home 文件系统:

tar zcvf - /home | ssh user@server "cat > /backup/home_fs.workstation_sep_21_09.tar.gz"
  • 大小写转换
v="Unix Philosophy"; echo $v | tr '[:lower:]' '[:upper:]'
echo 'tHIs IS A TeSt' | tr '[:upper:]' '[:lower:]'
  • 生日电子邮件提醒
echo "/usr/bin/mail -s 'Birthday gift for Julia' vivek@gite.in < /dev/null" | at 17:45
  • 创建一个 ISO CD 映像

从 /home/vivek/photos 目录的内容创建一个 ISO cdrom 映像:

mkisofs -V Photos -r /home/vivek/photos | gzip -9 > /tmp/photos.iso.cd.gz

您可以使用以下语法刻录 ISO cdrom 映像:

gzip -dc /tmp/photos.iso.cd.gz | cdrecord -v dev=/dev/dvdrw -

也可以创建 ISO 映像并将其直接刻录到 cd:

mkisofs -V Photos -r /home/vivek/photos | cdrecord -v dev=/dev/dvdrw -
  • 创建一个随机密码
tr -dc A-Za-z0-9_ < /dev/urandom  | head -c12 | xargs

Filter

如果 Linux 命令从标准输入接受其输入数据并在标准输出上产生其输出(结果),则称为过滤器。过滤器通常与 Linux 管道一起使用。

command1 | command2
command1 file.txt | command2
command1 args < input.txt | command2

其中,command2 是过滤器命令。在此示例中,grep 命令充当过滤器(它将从其输入中过滤出名称 vivek):

cut -d: -f1 /etc/passwd | sort | uniq | grep vivek

使用 grep 命令过滤 ps 命令输出:

ps aux | grep php-cgi

考虑以下示例:

sort < sname | uniq > u_sname

uniq 命令是 filter,它从 sort 命令获取输入并将输出作为输入传递给 uniq 命令;然后,uniq 命令输出重定向到 u_sname 文件。在 Linux 和 UNIX 之类的操作系统下,grep 命令被认为是最受欢迎的过滤器之一。

Links

上一页
下一页