여러 쉘에서 스크립트를 실행 중이신가요?

여러 쉘에서 스크립트를 실행 중이신가요?

두 개의 서버가 있습니다. 하나는 기본 쉘 ksh가 있는 AIX이고 다른 하나는 기본 쉘 bash가 있는 RHEL입니다.

유사한 명령을 실행하지만 AIX 또는 Linux용으로 스크립트를 설치했습니다. 스크립트가 bash 서버에서 실행되지 않습니다. bash 및 ksh에서 스크립트를 실행하는 방법이 있습니까, 아니면 두 개의 다른 스크립트를 생성하는 가장 좋은 옵션이 있습니까?

#!/usr/bin/ksh
export OS=`uname -s`
echo "OS is "$OS"."
case $OS in
        "AIX")
                #run AIX commands;;
        "Linux")
                #run Linux commands;;
        "*")
                echo "Exiting. The OS type is not found.";;
esac
echo "Done."
exit 0

고쳐 쓰다

내가 실행해야 하는 명령은 각 서버의 사용자 계정에 대한 것입니다. 계정 잠금 해제의 예. AIX /usr/bin/chuser account_locked=false $USERNAME

Linux /usr/bin/passwd -u $사용자 이름

추가 조사를 통해 AIX의 셸 위치는 /usr/bin/sh에 있는 반면 Redhat의 셸 위치는 /bin/sh에 있음을 발견했습니다.

"uname"의 결과를 기반으로 shebang을 정의할 수 있나요?

답변1

가장 쉬운 방법은 두 시스템 모두에서 동일한 셸을 사용하는 것입니다. 쉘이 사전 설치되어 제공된다고 해서(스크립트에 대한 "기본 쉘" 같은 것은 없으며, 쉘은 shebang 줄에서 말하는 대로임) 다른 쉘을 설치할 수 없다는 의미는 아닙니다. AIX에 bash를 설치할 수 있습니다(공구 상자, 예를 들어) 또는 Linux의 경우 ksh93(배포판의 패키지 관리자 사용: 패키지 설치 ksh).

ksh를 선택하는 경우 /usr/bin/kshAIX에서는 ksh88입니다. Linux에는 ksh88 버전이 없으며 /usr/bin/ksh93AIX에서 사용 가능한 ksh93 버전만 있습니다.

두 시스템의 동일한 위치에 동일한 쉘을 설치하면(심볼릭 링크가 가능함) shebang 라인에서 동일한 경로를 사용할 수 있으면 더 쉬울 것입니다. 동일한 위치를 갖는 것이 너무 어려운 경우 두 시스템 모두에 있는지 #!/usr/bin/env bash확인하는 한 유사한 것을 사용할 수 있습니다 . 이는 루트 액세스 권한이 없기 때문에 홈 디렉터리에 bash 또는 ksh를 설치해야 하는 경우 유용할 수 있습니다.bashPATH

실제로 두 시스템에 동일한 쉘을 설치할 수 없는 경우(아마도 사람들의 삶을 복잡하게 만들지만 뒤집기에는 너무 뿌리 깊은 어리석은 규정 준수 규칙이 있기 때문일 수 있음) 몇 가지 가능성이 있습니다.

  • #!/bin/sh시스템에서 제공하는 크로스 와이어 및 프로그램 으로 사용하십시오 . 모든 최신 UNIX 시스템은 다음을 제공합니다.POSIX 쉘처럼 /bin/sh. AIX에서는 /bin/shksh88입니다. Red Hat에서는 /bin/shbash입니다(로 호출하면 약간 다르게 동작함 sh). 일부 다른 운영 체제(예: 많은 Linux 배포판)에서는 /bin/shPOSIX보다 더 많은 기능을 갖고 있지 않을 수 있는 작은 셸입니다.
  • 더 나은 쉘을 찾아 실행하는 일부 상용구 코드로 스크립트를 시작하십시오.

    #!/bin/sh
    if [ -n "$BASH" ]; then
      … bash compatibility code …
    elif type whence >/dev/null 2>/dev/null; then
      … ksh compatibility code …
    elif type ksh93 >/dev/null 2>/dev/null; then
      exec ksh93 "$0" "$@"
    elif type ksh >/dev/null 2>/dev/null; then
      exec ksh "$0" "$@"
    elif type mksh >/dev/null 2>/dev/null; then
      exec mksh "$0" "$@"
    elif type bash >/dev/null 2>/dev/null; then
      exec bash "$0" "$@"
    else
      echo 1>&2 "Cannot find ksh or bash, aborting"
      exit 125
    fi
    

두 경우 모두 ksh88과 bash의 교차점은 POSIX 이상의 유용한 기능을 제공하지만 일부 호환성 코드가 필요할 수 있습니다. 특히:

  • ksh88에서 배열 할당 사용을 set -A참조하세요.다양한 ksh 환경의 할당 변수
  • 지역 변수는 으로 선언됩니다 typeset.
  • Ksh88 아니요 ${VAR/PATTERN/REPLACEMENT}, $'…'또는 FIGNORE. 그렇습니다 [[ … ]].
  • @(…)Bash에서 ksh 및 기타 ksh 확장 모드를 활성화 하려면 를 실행하세요 shopt -s extglob.

답변2

두 가지 별도 버전의 스크립트를 사용하는 것이 더 쉬울 수도 있습니다. 너무 짧기 때문에 jw013이 제안한 대로 두 형식 간의 차이점을 처리하기 위해 추가 코드를 추가하는 것은 가치가 없을 것입니다. 반면에 더 큰 스크립트가 있는 경우 하나의 스크립트를 사용하고 실행 위치에 따라 다른 명령을 실행하는 것이 더 쉬울 수 있습니다.

답변3

비슷한 요구 사항이 있습니다. AIX 5.3에서 ksh93을 사용하여 연관 배열을 지원해야 합니다. 그래서 ksh93을 사용하여 두 번째 인스턴스를 시작하는 스크립트를 설정했습니다. 또한 반복해서 다시 생성되는 것을 방지하기 위해 보호 기능도 추가했습니다.

#!/bin/ksh

scr=$0
safe=$1
echo "Check OS to determine if ksh93 is needed..."
if ( `typeset -A testvar > /dev/null 2>&1` ); then
  echo "Associative array functions supported."
else
  echo "Associative array functions NOT supported. Starting second instance with ksh93..."
  if [ "$safe" -eq 1 ]; then
    echo "SECOND INSTANCE ALREADY STARTED!"
    exit 1
  else
    echo "BEGIN SECOND INSTANCE USING KSH93"
    /bin/ksh93 $scr 1
    exit 0
  fi
fi

답변4

Giles의 답변은 (IMHO) 훌륭합니다(언제나 그렇듯이). 하지만 선택하지도 않았고 투표도 하지 않았기 때문에 너무 복잡하다고 생각했을 수도 있습니다. 따라서 도움이 될 수도 있고 그렇지 않을 수도 있는 몇 가지 (간단한) 사항이 있으며, 시간이 지남에 따라 유지 관리해야 하는 대규모 스크립트로 인해 문제가 발생할 수 있는 두 개의 개별 스크립트를 유지 관리하는 것을 피하는 데 도움이 될 수 있습니다.

1) bash대화식 사용을 위한 기본 쉘이 아니더라도 AIX 시스템에 설치되어 있을 수 있습니다. (제가 사용하고 있는 AIX 머신에는 이 기능이 bash설치되어 있지만 시스템 관리자가 추가했는지는 모르겠습니다. 우리 시스템 관리자는 모두 ksh마약 중독자이기 때문에 그런 식으로 설치한 것 같습니다.) 저는 기꺼이 그렇게 할 것입니다. RHEL 시스템에 베팅했습니다 ksh. 이미 설치되어 있습니다. 두 시스템에서 동일한 쉘을 사용할 수 있으면 절약할 수 있으므로 이것을 확인하십시오.많은문제.

2) 쉘이 어디에 설치될지 모르는 경우, 쉘 경로를 shebang 라인에 직접 입력하지 마십시오. 대신 아래와 같이 경로 env와 셸 실행 파일 이름을 입력하세요.

#!/usr/bin/env bash

이것~해야 한다두 컴퓨터 모두에서 작동하지만 확실히 알아보려면 테스트해야 합니다. ( env또는 대부분의 사물의 입장보다 의 입장이 더 표준적이라고 주장합니다 .)bash

두 시스템 모두에서 동일한 셸을 사용하면 문제가 해결될 수 있습니다. 하지만 그렇지 않다면...

3) 소스 코드의 플랫폼별 코드를 기본 스크립트 내의 함수로 나눌 수 있습니다. 즉, 스크립트에위치AIX에서 실행하는지 RHEL에서 실행하는지에 따라 상황이 다르게 작동하므로 플랫폼을 다시 확인할 필요가 없습니다. 한 번만 수행하면 적절한 기능을 얻을 수 있습니다.

case $OS in
    "AIX")
            source aix_functions;;
    "Linux")
            source redhat_functions;;
    "*")
            echo "Exiting. The OS type is not found.";;
esac

case이제 플랫폼을 구별하기 위해 추가 문을 사용하지 않고도 스크립트 전체에서 얻을 수 있는 모든 기능을 사용할 수 있습니다 .

do_something_platform_specific "$SOME_ARGUMENT" "$SOME_OTHER_ARGUMENT"

관련 정보