변수 값을 명령의 stdin에 전달하는 방법은 무엇입니까?


105

나는 다소 안전해야하는 쉘 스크립트를 작성 중입니다. 즉, 명령 매개 변수를 통해 보안 데이터를 전달하지 않고 임시 파일을 사용하지 않는 것이 좋습니다. 명령의 stdin에 변수를 어떻게 전달할 수 있습니까? 또는 가능하지 않은 경우 이러한 작업에 임시 파일을 올바르게 사용하는 방법은 무엇입니까?


공격자가 변경할 수 있습니까 $PATH? 그래서 그것은 cat교체 될 수 있습니다/bin/cat "$@" | tee /attacker/can/read/this/file
12431234123412341234123

답변:


74

다음과 같이 간단합니다.

echo "$blah" | my_cmd

7
변수의 공백을 조심하십시오 : echo "$blah"더 좋습니다.
Jonathan Leffler 2011 년

13
blah=-n, blah=-e... printf대신 사용 하는 방법을 살펴 보겠습니다 . unix.stackexchange.com/questions/65803/...
카밀로 마틴

1
이것은 깨지기 쉽고 오류가 발생하기 쉬운 것처럼 보입니다.
ThorSummoner

19
육년에, 나는 (하지만 난 그것을 받아 됐어요 수 없기 때문에 ...) 나는 것이 답변을 삭제할 수 있다면
올리버 찰스 워드

1
@OliverCharlesworth, 왜 그것을 사용하도록 편집하지 printf '%s\n' "$blah"않습니까? 그 하나의 변경으로 ( echo's 사양 의 많은 함정을 피하고, Stephane의 탁월한 답변은 Why is printfbetter than echo? on Unix & Linux , 또는 echo사양 의 APPLICATION USAGE 섹션 에서 더 간략하게 다룹니다. ) 합리적인 대답.
Charles Duffy

192

bashstdin 에서 값을 전달하는 것은 다음과 같이 간단합니다.

your-command <<< "$your_variable"

항상 변수 표현식 주위에 따옴표를 넣으십시오!

이것은 아마도에서만 bash작동하고에서는 작동하지 않을 것이라는 점에주의하십시오 sh.


39
Herestrings <<<는 사용 가능 하다는 보장이 없으며 내가 아는 한 POSIX 기반이 아닙니다. 에서 실행하는 한 예상대로 작동합니다 bash. OP는 특별히 'bash'가 아니라 'shell'이라고 말했기 때문에 언급했습니다. 그가 질문에 태그를 달았음에도 불구하고 bash... 그래서 이것은 여전히 ​​명백한 대답입니다.
JM Becker

이 경우도 있지만 echo파이프 생성으로 인해 방법을 사용하면 민감한 정보가 더 쉽게 유출 될 수 있습니다 . herestring 명령은 전적으로에 의해 처리됩니다 bash. 비록이 상황에서 (설명한대로) bash에서 작동한다는 것을 더 잘 알고 있었지만 그렇지 않으면 herestring을 지원하지 않아 생성 된 오류 메시지도 해당 정보를 유출 할 것입니다.
Steven Lu

@StevenLu Wait echo는 내장되어 있습니다. 거기에 파이프가 없죠? 유닉스이지만 그다지 유닉스가 될 수는 없습니다 .
Camilo Martin

4
@StevenLu printf '%s\n' "$var"는 동일한 결과를 생성 echo "$var"하지만 예를 들어, var=-enbash가 필요하지 않은 경우 중단 되지 않습니다.
Camilo Martin

1
여기 문자열의 문자열에 개행 문자가 추가됩니다.
pdr

19

' echo "$var" | command연산은 표준 입력이 에코 된 라인으로 제한됨을 의미합니다. 터미널도 연결하려면 더 멋져 야합니다.

{ echo "$var"; cat - ; } | command

( echo "$var"; cat -   ) | command

즉, 첫 번째 줄은 내용이 $var되고 나머지는 cat표준 입력 을 읽음으로써 나옵니다 . 명령이 너무 멋진 작업을 수행하지 않으면 (명령 줄 편집을 켜거나 실행하는 것처럼 실행 vim) 문제가 없습니다. 그렇지 않으면 정말 멋져 expect보일 필요가 있습니다. 또는 그 파생물 중 하나가 적절할 것 같습니다.

명령 줄 표기법은 실질적으로 동일하지만 두 번째 세미콜론은 중괄호와 함께 필요하지만 괄호는 사용하지 않습니다.


( echo "$LIST"; cat - ) | sed 1q이것은 나를 위해 작동하지만이 스크립트를 실행할 때 Ctrl d를 눌러야합니까?
Gert Cuykens 2010 년

예; 는 cat -당신이 입력 제어-D에 의해 EOF를 알려줄 필요가 있으므로, EOF 또는 인터럽트 될 때까지 키보드를 계속 읽습니다.
Jonathan Leffler

EOF 주위에 방법이 있습니까? sed 고양이 필요
Gert Cuykens 2010 년

cat첫 번째 줄에서와 같이 터미널 입력을 원하지 않는 경우 전혀 사용할 필요가 없습니다. 또는 cat파일을 나열하는 데 사용할 수 있습니다 . 또는 ... 명령이 터미널 입력을 읽도록하려면 입력 끝에 도달했을 때이를 알려야합니다. 또는 사용할 수 있습니다 ( echo "$var"; sed /quit/q - ) | command; 이것은 '종료'를 포함하는 줄을 입력 할 때까지 계속됩니다. 당신은 그것을 다루는 방법으로 끝없이 창의력을 발휘할 수 있습니다. 사용자가 에콰도르에서 작업을 시작했을 때 작동을 멈춘 프로그램에 대한 오래된 도시 전설을 조심하십시오. 그들은 수도 인 키토의 이름을 입력하고 프로그램이 종료되었습니다.
Jonathan Leffler

그렇게 말씀하시면 좋습니다. 하지만 왜 안돼 echo "$LIST" | sed 1q | ...? 그것은 모두 당신이 무엇에 관한 것인지에 달려 있습니다. <<EOF표기는 파일 내려 자신의 어딘가에서 행의 시작에서 EOF를 필요로한다. 나는 그것을 사용하지 않을 것이라고 생각한다. 그러나 나는 당신이 성취하고자하는 것이 무엇인지 여전히 잘 모르겠다. 실제로는 간단 echo "$LIST" | command하거나 echo $LIST | command아마도 충분할 것입니다 (그리고 둘 사이의 차이의 중요성을 아는 것이 중요합니다).
Jonathan Leffler

16

나는 Martin의 대답을 좋아했지만 변수에 무엇이 있는지에 따라 몇 가지 문제가 있습니다. 이

your-command <<< """$your_variable"""

변수에 "또는!


4
그런데 왜? 또한 문제를 재현 할 수 없습니다 foo1=-; foo2='"'; foo3=\!; cat<<<"$foo1"; cat<<<"$foo2"; cat<<<"$foo3". 잘 작동합니다. 세 사람 "은 정확히 무엇을 합니까? AFAIK 당신은 빈 문자열을 앞에 붙이고 추가합니다.
phk

진짜를 시도하십시오. 귀하의 명령은 ssh somehost입니다. 변수는 쉘 스크립트입니다.
Robert Jacobs

16
(cat <<END
$passwd
END
) | command

cat정말 필요하지 않지만 더 나은 코드를 구성하는 데 도움이 당신이 당신의 명령에 입력으로 괄호에 더 많은 명령을 사용할 수 있습니다.


그러나이 방법을 사용하면 명령에 여러 줄을 전달할 수 있고 공백도 허용합니다.$passwd
PoltoS

4
이것은 변수 내용을 파이프 또는 프로세스 스누핑으로 유출하지 않는 가장 좋은 답변입니다.
user2688272 17:06에

8

Martin의 답변에 따라 Here Strings 라는 bash 기능 이 있습니다 (자체가 더 널리 지원되는 Here Documents 기능 의 변형입니다 ).

http://www.gnu.org/software/bash/manual/bashref.html#Here-Strings

3.6.7 여기 문자열

여기 문서의 변형 형식은 다음과 같습니다.

<<< word

단어가 확장되어 표준 입력의 명령에 제공됩니다.

Here Strings는 bash 전용으로 표시되므로 이식성을 높이려면 PoltoS의 답변에 따라 원래 Here Documents 기능을 사용하는 것이 좋습니다.

( cat <<EOF
$variable
EOF
) | cmd

또는 위의 더 간단한 변형 :

(cmd <<EOF
$variable
EOF
)

다른 명령으로 추가로 리디렉션하지 않으려면 (및 을 생략 할 수 있습니다 ).


5

이 강력하고 이식 가능한 방법은 이미 의견에 나타났습니다. 독립형 답변이어야합니다.

printf '%s' "$var" | my_cmd

또는

printf '%s\n' "$var" | my_cmd

노트:

  • 그것은보다 낫다 echo: 이유가 여기 printf보다 더 echo?
  • printf "$var"잘못되었습니다. 첫 번째 인수는 %s또는 같은 다양한 시퀀스 \n해석 되는 형식 입니다. 변수를 오른쪽으로 전달하려면 형식으로 해석되지 않아야합니다.
  • 일반적으로 변수에는 후행 줄 바꿈이 포함되지 않습니다. 이전 명령 (와 함께 %s)은 변수를 그대로 전달합니다. 그러나 텍스트로 작동하는 도구는 불완전한 줄을 무시하거나 불평 할 수 있습니다 ( 텍스트 파일이 줄 바꿈으로 끝나는 이유 참조 ). 따라서 %s\n변수 내용에 개행 문자를 추가하는 후자의 명령 (와 함께 )을 원할 수 있습니다 . 분명하지 않은 사실 :

    • 여기서 Bash ( <<<"$var" my_cmd)의 문자열은 개행을 추가합니다.
    • 줄 바꿈을 추가하는 모든 메서드 my_cmd는 변수가 비어 있거나 정의되지 않은 경우에도 비어 있지 않은 stdin of 를 생성합니다.

4

이 시도:

echo "$variable" | command

하지만 $ variable 내용이 예를 들어 ps -uecho가 실행될 때 의 출력에 표시되지 않습니까?

2
아니에요. echo내장되어 있으므로 ps에 표시 할 프로세스가 없습니다
unbeli

2
변수의 공백을 조심하십시오 : echo "$variable"더 좋습니다.
Jonathan Leffler 2011 년

맞습니다, bash는 이중 공간을
차지하고

-1

그냥 해:

printf "$my_var" | my_cmd

var에 공백이 없으면 따옴표를 생략 할 수 있습니다.
bash를 사용하는 경우 다음을 수행 할 수도 있습니다.

echo -n "$my_var" | my_cmd

-n없이 echo를 사용하지 마십시오. 마지막에 줄 바꿈이 추가 된 vraiable을 파이프하기 때문입니다.


1
$ my_var가이면 작동하지 않으며 %sprintf는 아무것도 인쇄하지 않습니다. my_var="%s"; printf "$my_var"; -시도 해볼까요 printf "%s" "$my_var" | my_cmd ?
hanshenrik
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.