>  기사  >  백엔드 개발  >  쉘 파이프 리디렉션에 대한 기본 튜토리얼

쉘 파이프 리디렉션에 대한 기본 튜토리얼

巴扎黑
巴扎黑원래의
2017-08-15 15:54:001305검색

파이프라인은 프로세스 간 통신 문제를 해결하기 위해 존재합니다. 이를 통해 두 프로세스 간에 데이터를 전송할 수 있으며, 한 프로세스의 출력 데이터가 입력 데이터로 다른 프로세스에 전송됩니다.

1.8.1 익명 파이프" | "

파이프 기호는 이름에서 알 수 있듯이 의미가 있습니다. 파이프와 같아서 파이프 입구에서 파이프 출구로 파이프를 통해 데이터를 전달합니다.

파이프라인은 프로세스 간 통신 문제를 해결하기 위해 존재합니다. 이를 통해 두 프로세스 간에 데이터를 전송할 수 있으며, 한 프로세스의 출력 데이터가 입력 데이터로 다른 프로세스에 전송됩니다. 파이프의 왼쪽은 데이터 제공자이고 파이프의 오른쪽은 데이터 수신자입니다.

예를 들어 echo "abcd" | passwd --stdin username은 echo 프로세스의 출력 결과 "abcd"가 프로세스 passwd의 입력 데이터로 사용된다는 의미입니다. echo "abcd" | passwd --stdin username,表示将进程echo的输出结果"abcd"作为进程passwd的输入数据。

基本的管道符号及其用法很容易理解。现在的疑问是,对于ps aux | grep "ssh"

기본적인 파이프 기호와 사용법은 이해하기 쉽습니다. 이제 문제는 ps aux | grep "ssh" 의 경우 grep 프로세스가 결과에 나타나는 이유는 무엇입니까?


[root@xuexi ~]# ps aux | grep ssh
root    1211 0.0 0.1 82544 3600 ?    Ss  Jul26  0:00 /usr/sbin/sshd -D
root   25236 0.0 0.2 145552 5524 ?    Ss  05:28  0:00 sshd: root@pts/0
root   25720 0.1 0.2 145416 5524 ?    Ss  06:15  0:00 sshd: root@pts/1
root   25770 0.0 0.0 112648  948 pts/1  S+  06:15  0:00 grep --color=auto ssh

일반적인 생각으로는 ps가 먼저 실행되고 출력을 받은 후 출력 데이터가 grep에 전달됩니다. 이때 grep은 아직 실행되지 않았지만 ps는 실행을 완료할 수 있습니다. 프로세스 정보가 계속 수집되나요? 그 이유는 파이프라인이 프로세스 간 통신을 구현하는데, 두 프로세스 간에 중복이 있기 때문입니다. ps 프로세스를 실행한 후 프로세스 정보 수집도 시작되어 데이터 수신을 기다리는 상태입니다. ps가 데이터를 수집하면 출력이 해제됩니다. 데이터는 메모리로 전달되고 필터링을 위해 grep으로 전달됩니다.

파이프의 본질은 데이터 전송입니다. 파이프 왼쪽의 출력 데이터는 메모리에 저장되고 파이프 오른쪽의 프로세스에서 읽혀집니다. 메모리가 출력 데이터를 완전히 저장할 만큼 충분하지 않은 경우 파이프 왼쪽의 프로세스는 파이프의 오른쪽이 메모리의 데이터 일부를 꺼낼 때까지 대기하여 파이프 왼쪽의 프로세스가 파이프는 계속해서 출력할 수 있으며 파이프 왼쪽의 프로세스가 시작된 직후 파이프 오른쪽의 프로세스가 시작되지만 파이프가 전달한 데이터를 수신하기 위해 대기 중인 상태였습니다. .

즉, 파이프라인의 왼쪽과 오른쪽 프로세스가 거의 순서 없이 실행됩니다.

그렇다면 ps aux | grep "ssh"는 어떻게 grep 자체 프로세스가 결과에 나타나는 것을 피할 수 있습니까? 두 가지 방법이 있습니다.

방법 1: ps aux | grep "ssh" | grep -v "grep"

방법 2: ps aux | grep "ss[h]"


[root@xuexi ~]# ps aux | grep ss[h]
root    1211 0.0 0.1 82544 3600 ?    Ss  Jul26  0:00 /usr/sbin/sshd -D
root   25236 0.0 0.2 145552 5524 ?    Ss  05:28  0:00 sshd: root@pts/0
root   25720 0.0 0.2 145416 5524 ?    Ss  06:15  0:00 sshd: root@pts/1
is grep의 "-v" 기능을 적용합니다. 방법 2는 정규식 기능을 적용하는 것입니다.

익명 파이프를 사용하는 과정에서 파이프 양쪽의 프로세스가 동일한 프로세스 그룹에 속해 있다는 사실을 발견했을 수 있습니다. 즉, 파이프 왼쪽의 데이터는 해당 프로세스에만 전달될 수 있습니다. 파이프의 오른쪽에 있으며 다른 프로세스에서는 이 데이터를 읽을 수 없습니다. 그러나 익명 파이프 외에도 명명된 파이프도 있습니다. 명명된 파이프는 프로세스의 데이터를 파이프 파일(fifo)에 저장합니다. 더 이상 리더가 제한되지 않습니다. 명명된 파이프에 대해서는 일반적으로 자세한 소개를 제공하는 Linux/unix 운영 체제 커널 또는 프로그래밍 서적을 참조하십시오.

1.8.2 리디렉션

1.8.2.1 리디렉션 기본

표준 입력(stdin), 표준 출력(stdout) 및 표준 오류 출력(stderr)에 대한 가장 일반적인 파일 설명자는 각각 0, 1입니다. 및 2 중 0, 1 및 2도 숫자 코드로 간주될 수 있습니다. 출력 정보는 화면에 출력되는 정보라고 생각하면 되는데, 에러가 나지 않는 것이 표준 출력이고, 에러 프롬프트가 나오는 것이 표준 에러 출력이다. 물론 이러한 설명은 편향되어 있다. , 그러나 이해하기 쉽습니다. 고급 리디렉션을 구현하기 위해 고유한 설명자를 사용자 정의할 수도 있습니다. 해당 사용법은 향후 문서에서 소개될 수 있습니다.

표준 입력 = /dev/stdin = 코드 0 = 4303bebe054262ad504488c8bf7f57fe>

표준 오류 = /dev/stderr = 코드 2 = 2> 또는 2>>

95ec6993dc754240360e28e0de8de30a, 2> 덮어쓰기 기능을 구현하고, >>, 2>> 추가 기능을 구현하지만 58d8640be8e925b5429be4d671cec312&1 및 &>는 둘 다 stdout과 stderr이 동일한 위치로 리디렉션됨을 나타냅니다. 즉, 모든 출력 콘텐츠가 리디렉션됩니다. 가장 일반적인 "&> /dev/null"과 같은 것입니다.

stdout 또는 stderr을 /dev/null에 던지는 것은 출력 정보를 삭제하는 것을 의미하며, /dev/null을 파일로 리디렉션하는 것은 파일을 지우는 것을 의미합니다.


[root@xuexi ~]# cat /dev/null > ab.sh

또한 파일을 빠르게 지울 수 있는 여러 가지 방법이 있습니다


🎜
[root@xuexi ~]# > ab.sh
[root@xuexi ~]# : > ab.sh       # 或"true >ab.sh",其实它们都等价于">ab.sh"
[root@xuexi ~]# echo '' > ab.sh
[root@xuexi ~]# truncate -s 0 ab.sh  # truncate命令用于收缩和扩展文件大小
[root@xuexi ~]# dd if=/dev/null of=ab.sh

最后最重要的一点:在有重定向符号的语句中,命令执行之前已经将文件截断了。所以如果正在编辑一个文件并将编辑的结果重定向回这个文件将出现异常,因为截断后就没有合适的内容用于编辑。一个简单的示例如下:


[root@xuexi ~]# head a.log > a.log

有些时候直接使用">"覆盖输出是比较危险的。可以使用set -C来设置如果输出重定向文件已经存在则不覆盖。使用set +C来取消set -C的效果。如果在设置了set -C时仍然想强制覆盖,可以使用“>|”代替“>”来重定向输出。同理错误输出也有此特性。


[root@xuexi tmp]# set -C
[root@xuexi tmp]# cat flip >ttt.txt
-bash: ttt.txt: cannot overwrite existing file
[root@xuexi tmp]# cat flip >| ttt.txt
[root@xuexi tmp]# set +C

1.8.2.2 cat和重定向配合

配合cat使用可以分行输入内容到文件中。


[root@xuexi tmp]# cat <<eof>log.txt  # 覆盖的方式输入到log.txt
> this is stdin character
> eof

也可以使用下面的方法。


[root@xuexi tmp]# cat >log1.txt <<eof 
> this is stdin character first!
> eof

一方面,eof部分都必须使用"88a41d6e50d3a6dd535eaf0181fbf000log1.txt表示将document的内容覆盖到log1.txt文件中,如果是要追加,则使用>>log1.txt。所以,追加的方式如下:


[root@xuexi tmp]# cat >>log1.txt <<eof 
> this is stdin character first!
> eof


[root@xuexi tmp]# cat <<eof>>log1.txt 
> this is stdin character first!
> eof

1.8.2.3 tee双重定向

可以使用tee双重定向。一般情况下,重定向要么将信息输入到文件中,要么输出到屏幕上,但是既想输出到屏幕又想输出到文件就比较麻烦。使用tee的双重定向功能可以实现该想法。如图。


tee [-a] file

选项说明:

    -a:默认是将输出覆盖到文件中,使用该选项将变为追加行为。

    file:除了输出到标准输出中,还将输出到file中。如果file为"-",则表示再输入一次到标准输出中。

例如下面的代码,将a开头的文件内容全部保存到b.log,同时把副本交给后面的的cat,使用这个cat又将内容保存到了x.log。其中"-"代表前面的stdin。


[root@xuexi tmp]# cat a* | tee b.log | cat - >x.log

还可以直接输出到屏幕:


[root@xuexi tmp]# cat a* | tee b.log | cat

tee默认会使用覆盖的方式保存到文件,可以使用-a选项来追加到文件。如:


[root@xuexi tmp]# cat a* | tee -a b.log | cat

现在就可以在使用cat和重定向创建文件或写入内容到文件的同时又可以在屏幕上显示一份。


[root@xuexi tmp]# cat <<eof | tee ttt.txt
> x y
> z 1
> eof
x y
z 1

1.8.2.4 <<和<<<

在bash中,<<和<<<是特殊重定向符号。<<表示的是here document,<<<表示的是here string。

here document在上文已经解释过了,对于here string,表示将<<<后的字符串作为输入数据。

例如:


passwd --stdin user <<< password_value

等价于:


echo password_value | passwd --stdin user

위 내용은 쉘 파이프 리디렉션에 대한 기본 튜토리얼의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.