명령을 직접 실행하는 것과 "bash -c"를 사용하는 것의 차이점은 무엇입니까?

명령을 직접 실행하는 것과 "bash -c"를 사용하는 것의 차이점은 무엇입니까?

bash -c명령(내장 또는 외부)의 경우 bash 쉘 프로세스에서 직접 실행하는 것과 bash 쉘에서 실행하는 것의 차이점은 무엇입니까? 서로 비교하면 어떤 장점과 단점이 있나요?

For example, in a bash shell, run `date` directly, and run `bash -c
date`. Also consider a builtin command instead of an external one.

답변1

  1. -c옵션을 사용하면 프로그램이 명령을 실행할 수 있습니다. 분할하고 수행하기가 훨씬 쉽습니다.

    execl("/bin/sh", "sh", "-c", "date | od -cb  &&  ps > ps.out", NULL);
    

    포크와 비교하면 파이프를 만들고, 다시 포크하고, execl각 하위 파이프라인을 호출하고, 호출하고 wait, 종료 상태를 확인하고, 다시 포크하고, 호출하고 close(1), 파일을 열고 파일 설명자 1에서 열려 있는지 확인한 다음 다른 execl. 나는 이것이 이 옵션이 애초에 만들어진 이유라고 생각합니다.

    라이브러리 system()함수는 위에서 설명한 대로 명령을 실행합니다.

  2. 임의로 복잡한 명령을 받아들이고 이를 간단한 명령처럼 보이게 만드는 방법을 제공합니다. 이는 사용자 지정 명령(예: 또는 )을 실행하는 프로그램에 find … -exec유용합니다 xargs. 하지만 당신은 이것이 당신의 질문에 대한 대답의 일부라는 것을 이미 알고 있었습니다. 복합 명령을 다른 명령의 인수로 지정하는 방법은 무엇입니까?
  3. 이는 bash가 아닌 대화형 셸을 실행하는 경우 유용합니다. 대신 bash를 실행하는 경우 이 구문을 사용할 수 있습니다

    $ash-c"주문하다"
     
    $ csh -c "주문하다"
     
    $대시-c"주문하다"
     
    $ zsh -c "주문하다"

    모든 쉘도 이 -c옵션을 인식하므로 다른 쉘에서 명령을 실행하십시오. 물론 다음과 같은 결과를 얻을 수 있습니다.

    $ 재
    재$주문하다
    회색$출구
     
    $csh
    csh$주문하다
    csh$ 종료
     
    $대시
    대시$주문하다
    대시$exit
     
    $ 지쉬
    zsh$주문하다
    zsh$ 종료

    나는 ash$ 다른 쉘 프롬프트를 설명하기 위해 등을 사용합니다. 실제로는 이를 얻지 못할 수도 있습니다.

  4. 예를 들어, "새로운" bash 쉘에서 명령을 실행하려는 경우 유용합니다.

    $ ls -lA
    total 0
    -rw-r--r-- 1 gman gman   0 Apr 14 20:16 .file1
    -rw-r--r-- 1 gman gman   0 Apr 14 20:16 file2
    
    $ echo *
    file2
    
    $ shopt -s dotglob
    
    $ echo *
    .file1 file2
    
    $ bash -c "echo *"
    file2
    

    또는

    $ type shift
    shift is a shell builtin
    
    $ alias shift=date
    
    $ type shift
    shift is aliased to ‘date’
    
    $ bash -c "type shift"
    shift is a shell builtin
    
  5. 위의 내용은 오해의 소지가 있는 지나치게 단순화된 내용입니다. bash가 실행될 때 -c고려됩니다.비대화형~/.bashrc쉘이며 지정 하지 않는 한 읽지 않습니다 -i. 그래서,

    $ 유형 CP
    cp의 별칭은 "cp -i"입니다.          # 정의된~/.bashrc
     
    $cp .file1 파일 2
    cp: "file2"를 덮어쓰시겠습니까? N
     
    $ bash -c "cp .file1 파일2"
                                      # 기존 파일을 확인 없이 덮어썼습니다!
    $ bash -c -i "cp .file1 파일2"
    cp: "file2"를 덮어쓰시겠습니까? N

    대신 -ci, -i -c또는 을 사용할 수 있습니다 .-ic-c -i

    이는 3단락에 언급된 다른 셸에도 어느 정도 적용될 수 있으므로 긴 형식(즉, 실제로 입력과 정확히 동일한 양의 두 번째 형식)이 더 안전할 수 있습니다. 특히 init/config 파일을 설정한 경우 더욱 그렇습니다. 그 껍질.

  6. ~처럼와일드카드 설명, 새 프로세스 트리(새 셸 프로세스 및 가능한 하위 프로세스)를 실행 중이므로 하위 셸에서 환경 변경이 이루어집니다. 할 수 없다상위 셸(현재 디렉터리, 환경 변수 값, 함수 정의 등)에 영향을 줍니다. 따라서 , 및 sh -c에  내장된 쉘이 상위 쉘에 의해 시작된 백그라운드 작업에 영향을 주거나 액세스할 수 없으며 이를 기다릴 수도 없다는 것을 상상하기 어렵습니다 . 본질적으로 그냥 실행하는 것과 동일합니다.fgbgjobswaitsh -c "exec some_program"some_program대화형 쉘에서 직접 일반적인 방법입니다.  sh -c exit그것은 큰 시간 낭비입니다.  ulimit그리고 umask자식 프로세스의 시스템 설정을 변경한 후 실행하지 않고 종료하는 것도 가능합니다.

    컨텍스트에서 작동하는 거의 유일한 내장 명령 sh -c은 입니다 kill. 물론 출력( echo, printfpwd) 만 생성하는 명령 type은 영향을 받지 않으며 파일에 쓰면 지속됩니다.

  7. 물론 내장된 기능을 사용할 수도 있습니다.이것과 결합 예를 들어, 외부 명령
    sh -c "CD디렉토리;프로그램"
    그러나 일반 서브셸을 사용하면 본질적으로 동일한 효과를 얻을 수 있습니다.
    (CD디렉토리;프로그램)
    어느 것이 더 효율적입니까? 유사한 것에 대해서도 마찬가지입니다(두 부분).
    sh -c "umask 77;프로그램"
    또는 ulimit(또는 shopt). 그 뒤에 임의로 복잡한 명령을 넣을 수 있으므로 (전체 쉘 스크립트의 복잡성까지) , , , , 등 -c의 내장 명령을 사용할 수 있습니다 .sourcereadexporttimessetunset

답변2

실행 bash -c "my command here"과 그냥 실행 의 주요 차이점 my command here은 전자는 하위 쉘을 시작하고 후자는 현재 쉘에서 명령을 실행한다는 것입니다.

내장 명령과 외부 명령은 실제로 중요하지 않습니다.아무것현재 셸이나 하위 셸에서 실행할 수 있습니다.

그러나 효과에는 많은 차이가 있습니다.

  • 서브셸의 환경 변경할 수 없다상위 셸(현재 디렉터리, 환경 변수 값, 함수 정의 등)에 영향을 줍니다.
  • 상위 셸에 설정되었지만 내보내지지 않은 변수는 하위 셸에서 사용할 수 없습니다.

이는 완전한 차이점 목록과는 거리가 멀지만 핵심 사항을 다룹니다. bash -c; 원래 쉘과는 다른 프로세스입니다.

서브셸을 생성하면 성능 저하가 발생할 수도 있습니다. 이는 스크립트가 자주 실행되거나 명령이 일종의 루프 내에 있는 경우 가장 관련이 있습니다.

답변3

-c 옵션은 기본적으로 파일 대신 CLI 인수로 제공되는 미니 쉘 스크립트를 실행합니다.

$ bash -c the_script the_scriptname 1 2 3 

실제로 다음과 같습니다.

$ echo the_script > the_scriptname
$ bash the_scriptname 1 2 3
$ rm the_scriptname

보시다시피:

$ bash -c 'printf " ->%s\n" $0 "$@"; echo $-;' scriptname 1 2 3
   ->scriptname
   ->1
   ->2
   ->3
  hBc

(영어: $0 == 스크립트 이름; $@ == (1 2 3); bash는 다음을 수행합니다. 시간재 주문 이행;두번째인종 확장 및 이미 -c깃발을 들고 실행 중)

그리고:

 $ echo 'printf " ->%s\n" $0 "$@"; echo $-;' > scriptname
 $ bash scriptname 1 2 3 
 ->scriptname
 ->1
 ->2
 ->3
 hB

답변4

-c 문자열

-c 옵션이 있으면 문자열에서 명령을 읽습니다. 문자열 뒤에 매개변수가 있으면 $0부터 시작하는 위치 매개변수에 할당됩니다.

나는 이것이 당신의 문제를 해결할 것이라고 생각합니다

관련 정보