shell script에서 parent,child process 간 특정 변수 공유 관련 질문입니다.

백연구원의 이미지

우선 제목이 맞는지 모르겠지만 하고자 하는것은 아래와 같습니다.

$ find ./ ! -type d | xargs -I{} sh -c "cp{} tmp/.;\
 if [ \$? == 0 ];then echo \"success\"; else \"failed\";fi"

파일을 복사하는 스크립트인데, 복사가 실패했을 때 메인(parent) 셸이 알수 있도록 child에서 환경 변수 등을 사용하는게 목표입니다.

parent에서 설정된 변수는 child에서 바로 사용가능하지만, 그 역으로는 안되는 것으로 알고 있습니다만, 혹시 이런 경우에 추천해주실만한 방법이 있을까요?

return은 함수가 아니라 안되고, exit는 다른 문제가 있는 것 같습니다.

exit를 했을때 아래와 같은 오류(?)가 나옵니다.

xargs: sh: 상태 255을 가지고 종료됨; 중단함

파일을 사용하라는 말씀만은 삼가해주세요 (...)

 의 이미지

성공/실패 여부만을 반환하고자 하는 것이라면 종료 코드가 가장 간편하죠.
문제는 xargs - sh - cp로 이어지는 체인을 거슬러 전달해줘야 한다는 것인데, 결국 이 모두의 매뉴얼을 다 보면 되겠습니다.

1) cp
https://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html#cp-invocation
복사가 성공하면 zero, 실패하면 non-zero

2) sh
뭐 스크립트를 짜기 나름이죠.
http://tldp.org/LDP/abs/html/exit-status.html
exit 명령의 경우 종료 코드를 명시적으로 지정해주지 않으면 $?, 그러니까 가장 마지막으로 실행한 명령의 종료 코드를 그대로 전달한다는군요.
그 "마지막 명령"이 cp라면 따로 손 쓰지 않아도 저희가 원하는 대로 되는 것 같네요. 사실 그렇게 할 경우엔 굳이 sh를 체인에 넣을 필요도 없이 xargs가 cp를 바로 실행하게 해도 됐겠습니다만.
어떻게든 종료 코드에 손을 대고 싶으면,
if [ $? == 0 ];then exit 0; exit 1;fi 와 같이 합시다.
non-zero 종료 코드를 강제로 1로 바꾸는 거죠.

3) xargs
http://man7.org/linux/man-pages/man1/xargs.1.html
여기서 좀 복잡해지는데

Quote:
If any invocation of the command exits with a status of 255, xargs will stop immediately without reading any further input. An error message is issued on stderr when this happens.

Quote:
xargs exits with the following status:
0 if it succeeds
123 if any invocation of the command exited with status 1-125
124 if the command exited with status 255
125 if the command is killed by a signal
126 if the command cannot be run
127 if the command is not found
1 if some other error occurred.

Exit codes greater than 128 are used by the shell to indicate that a
program died due to a fatal signal.

xargs로 인해 실행되는 프로그램이 255를 반환하면 xargs는 즉시 멈춥니다. 즉, 한 번의 실패가 곧바로 xargs 전체의 종료로 만들고 싶을 때는 255를 반환하게 하면 됩니다.
그렇지 않은 경우, 즉 몇 번쯤 실패하더라도 보고는 하되 계속 진행하게 만들고 싶을 경우에는 적당히 1~125 사이의 종료 코드를 반환하게 만들면 되는 거죠.

어느 쪽이 질문자님의 의도에 맞는지는 지금으로선 질문자님밖에 모르시는 것 같네요. 하지만 일단 질문자님이 겪은 상황, 그러니까 xargs가 "상태 255을 가지고 종료됨"을 보고하는 상황은 위 매뉴얼을 보시면 이해하실 수 있으리라고 봅니다. 피할 수도 있고요.

마지막으로 한 가지 더. sh에서 파이프로 연결된 명령어를 실행된 뒤 $?의 값은, 파이프의 마지막 명령어의 종료 코드로 세팅됩니다. 결국, 질문자님의 의도에 따라 두 가지 해답이 있는 거네요.

#cp가 실패하면 곧바로 xargs가 종료되며 stderr에 메시지를 출력하고, exit_code에는 124가 들어갑니다. 성공하면 당연히 0이 들어가고요.
find ./ ! -type d | xargs -I{} sh -c "cp{} tmp/.; if [ \$? == 0 ];then exit 0; else exit 255;fi"
exit_code=$?

#cp가 몇 번 실패하더라도 xargs는 끝까지 실행합니다. 그런 경우엔 exit_code에는 123이 들어가겠죠. 모두 성공하면 마찬가지로 당연히 0.
find ./ ! -type d | xargs -I{} sh -c "cp{} tmp/.; if [ \$? == 0 ];then exit 0; else exit 1;fi"
exit_code=$?
백연구원의 이미지

습관적으로 exit 255으로 했었는데 여기서 차이가 있었군요, 원하던 것은 두 번째 예제였습니다.
시간내어 답변 주셔서 감사합니다 :-)


소곤소곤

bushi의 이미지

child 프로세스에서 parent 의 환경변수를 직접 조작할 수 있는 방법은 없습니다.
만약 있다면 시스템 보안에 치명적입니다.

파일로의 redirection 이 싫다면 pipe 로 직접 받으세요.

[schoi0@SEL-SCHOI0-D2 tmp]$ tree -p
.
├── [-rw-rw-r--]  a
├── [-rw-rw-r--]  b
├── [-rw-rw-r--]  c
├── [-rw-rw-r--]  d
└── [drwxrwxr-x]  tmp
 
1 directory, 4 files
[schoi0@SEL-SCHOI0-D2 tmp]$ x=$(find ! -type d | while read ent; do x=$(cp $ent tmp/ 2>&1); [ -n "$x" ] && echo "#File:\"$ent\" Error:\"$x\""; done)
[schoi0@SEL-SCHOI0-D2 tmp]$ (IFS=$'#\n'; for err in $x; do [ -n "$err" ] && echo ERROR: $err; done)
[schoi0@SEL-SCHOI0-D2 tmp]$ 
[schoi0@SEL-SCHOI0-D2 tmp]$ tree -p
.
├── [-rw-rw-r--]  a
├── [-rw-rw-r--]  b
├── [-rw-rw-r--]  c
├── [-rw-rw-r--]  d
└── [drwxrwxr-x]  tmp
    ├── [-rw-rw-r--]  a
    ├── [-rw-rw-r--]  b
    ├── [-rw-rw-r--]  c
    └── [-rw-rw-r--]  d
 
1 directory, 8 files
[schoi0@SEL-SCHOI0-D2 tmp]$ x=$(find ! -type d | while read ent; do x=$(cp $ent tmp/ 2>&1); [ -n "$x" ] && echo "#File:\"$ent\" Error:\"$x\""; done)
[schoi0@SEL-SCHOI0-D2 tmp]$ (IFS=$'#\n'; for err in $x; do [ -n "$err" ] && echo ERROR: $err; done)
ERROR: File:"./tmp/d" Error:"cp: './tmp/d' and 'tmp/d' are the same file"
ERROR: File:"./tmp/c" Error:"cp: './tmp/c' and 'tmp/c' are the same file"
ERROR: File:"./tmp/a" Error:"cp: './tmp/a' and 'tmp/a' are the same file"
ERROR: File:"./tmp/b" Error:"cp: './tmp/b' and 'tmp/b' are the same file"
 
[schoi0@SEL-SCHOI0-D2 tmp]$ (IFS=$'#\n'; for err in $x; do [ -n "$err" ] && (IFS=$'"\n'; y=($err); echo Error for the file \"${y[1]}\"; echo "  ${y[3]}".); done)
Error for the file "./tmp/d"
  cp: './tmp/d' and 'tmp/d' are the same file.
Error for the file "./tmp/c"
  cp: './tmp/c' and 'tmp/c' are the same file.
Error for the file "./tmp/a"
  cp: './tmp/a' and 'tmp/a' are the same file.
Error for the file "./tmp/b"
  cp: './tmp/b' and 'tmp/b' are the same file.
백연구원의 이미지

하긴.. 보안에 홀을 만들겠군요 (...) 파이프 처리는 눈에 익숙하지 않아서 지양하고 있었는데 한수 잘 배워갑니다.
답변 정말 감사드립니다. :-)


소곤소곤

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.