Linux shell中&,&&,|,||的用法

前言

在玩dvwa的命令注入漏洞的时候,遇到了没有预料到的错误,执行
ping 127.0.0.1 & echo "<?php phpinfo(); ?>" > shell.php
发现返回的执行结果如下图

QQ截图20190207161915.jpg
理论上在dvwa的根目录里应该有一个shell.php但是并没有出现

root@kali:/var/www/html/dvwa# ls
about.php     docs         hackable          login.php    README.md     test.php
CHANGELOG.md  dvwa         ids_log.php       logout.php   robots.txt    vulnerabilities
config        external     index.php         phpinfo.php  security.php
COPYING.txt   favicon.ico  instructions.php  php.ini      setup.php
root@kali:/var/www/html/dvwa# 

原因

经几次尝试,发现问题出在&上。将其换成|就可以完成写入shell,但是对& && | ||的功能不是很了解,于是在Linux终端尝试了一下,基本上搞清楚了涵义和用法

看结论请直接拉到最后点这里

尝试过程

使用了一个Linux命令sleep,输入sleep --help显示帮助,系统给出的介绍如下:

root@kali:~# sleep --help
Usage: sleep NUMBER[SUFFIX]...
  or:  sleep OPTION
Pause for NUMBER seconds.  SUFFIX may be 's' for seconds (the default),
'm' for minutes, 'h' for hours or 'd' for days.  Unlike most implementations
that require NUMBER be an integer, here NUMBER may be an arbitrary floating
point number.  Given two or more arguments, pause for the amount of time
specified by the sum of their values.

      --help		显示此帮助信息并退出
      --version		显示版本信息并退出

root@kali:~# 

其余的是简单的ifconfig、uname和echo命令

还有一条设定:cmd1 操作符 cmd2 操作符 cmd3 ......,把整个称作一个命令

&

执行ifconfig & echo hello,返回的执行结果如下:
QQ截图20190207165708.jpg
这个结果有一些值得注意的点,一是奇怪的[1] 3187,二是先显示的hello(执行了echo),再另起一行显示了ifconfig的结果,按说应该是先执行ifconfig显示网络配置信息,接着才应该执行echo,三是最后的已完成,这与平常命令执行结束明显的不同

执行echo hello & ifconfig,返回的执行结果如下:
QQ截图20190207170736.jpg
对比上个命令的执行结果,有很多不同。这个结果貌似是符合我们的预期的,先执行了echo再执行了ifconfig,但是还有莫名的方框数字和已完成

上网以关键词linux &查询到,在Linux下,命令之后加上&,表示把该命令以后台方式执行。其中,[1]表示后台任务的标识,之后的数字表明后台执行的任务的UID,那就意味着shell将这个后台命令以多进程的方式在运行。

于是猜想cmd1 & cmd2执行的方式是以后台方式执行cmd1,同时执行cmd2。验证如下:
QQ截图20190207173959.jpg
echo命令执行较快,于是首先输出了hello,sleep强制停止了5秒,于是在后台显示在运行中,5秒之后完成。

&&

&没有逻辑功能,那么猜想&&真正完成了逻辑与的功能,从左到右依次执行各项命令

动态效果不好演示,可以通过输入sleep 5 && echo ends看一下动态的效果。执行的结果确实是暂停了5秒,之后显示了ends

但是还可以以其他方式表现,譬如如下的命令
QQ截图20190207175818.jpg
很明显的证明cmd1和cmd2的执行顺序关系

此时应有补充资料:

shell 在执行某个命令的时候,会返回一个返回值,该返回值保存在 shell 变量 $? 中。当 $? == 0 时,表示执行成功;当 $? != 0 时,表示执行失败。

这篇博文详细的列出了Linux里的返回值,供参考

由编程的知识很容易理解,0&&!0 ==0,这样,任意一个cmd出现了错误,只要有可以正确执行返回0的cmd,整体命令返回值就是0,将不会影响到其他cmd的执行,只会单独关于某个错误的cmd报一个错误

|

鉴于&不表示逻辑与,那么|也不一定表达逻辑或的含义,实验一下命令
QQ截图20190207213130.jpg

发现第一条命令输出了hello,同时命令并没有终止,光标等待了5秒之后,才另起一行。这表明两个子命令一起被执行,但是与&不同,cmd1被放在前台执行。可以推断shell将cmd1和cmd2分为两个线程执行。

发现第二条命令没有显示ifconfig应有的输出,但是如下图所示:
QQ截图20190207214207.jpg
可以看到,cmd1实际上已经被执行了,只是返回的信息没有被显示在终端上

那么可以总结出,cmd1 | cmd2中,cmd1和cmd2同时在前台被执行,但是cmd1的执行结果不会被显示在终端上。

||

跟&&类似,cmd之间使用||接,从而实现逻辑或的功能

实验如下命令:
QQ截图20190207222255.jpg

只有在||左边的命令返回假(命令返回值 $? != 0),||右边的命令才会被执行。这和 c 语言中的逻辑或语法功能相同,(0||!0 == 0),即实现短路逻辑或操作。同时,只要有一个命令返回真(命令返回值 $? == 0),后面的命令就不会被执行,直到返回真的地方停止执行。

总结

再看一下设定:cmd1 操作符 cmd2 操作符 cmd3 ......,把整个称作一个命令

&:除了最后一个cmd,前面的cmd均已后台方式静默执行,执行结果显示在终端上,个别的cmd错误不影响整个命令的执行,全部的cmd同时执行

&&:从左到右顺序执行cmd,个别cmd错误不产生影响

|:各个cmd同时在前台被执行,但是除最后的cmd之外,其余的执行结果不会被显示在终端上

||:从左到右顺序执行cmd,只有左侧的cmd执行出错,右边的cmd才会被执行,同时一旦有cmd被成功执行,整个命令就会结束,返回终端

posted @ 2019-02-07 22:59  柏凝  阅读(31762)  评论(0编辑  收藏  举报