만약 회사에서 여러분이 관리하는 리눅스 서버 수백대의 패스워드를 전부 변경하라고 지시했다면 어떻게 하겠습니까? 그것도 전부 동일한 패스워드가 아니라 나름대로의 규칙을 따르는 패스워드로 말이죠. 이 글은 제가 생각해본 방법을 소개하면서, 여러 고수님들의 조언을 듣고자 포스팅하는 것입니다.

과제
1. 리눅스 서버 수백대의 root 패스워드를 전부 변경하시오.
2. 패스워드는 아래 규칙을 따릅니다.
- 앞 부분엔 !@#이 붙는다.
- 그 다음엔 각 서버 hostname의 끝 3자리가 들어간다.
- 마지막엔 sbox가 붙는다.

예를 들어 snoopyWeb01 이라는 서버의 경우 비밀번호는 아래와 같이 변경해야 합니다.
!@#b01sbox

일단 제가 생각한 명령어는 아래와 같습니다.

echo \!@#$(hostname | tail -c 4)sbox | passwd --stdin root


고수분들께 질문드리고 싶은 내용이 있는데 제가 처음에는 echo 다음에 ! 앞에 백슬러시를 안 붙여서 오류에 봉착했습니다. 그래서 여러가지 시도해본 결과 !가 수상해서 escape 시켜줬는데요, 리눅스에서 !가 하는 역할이 무엇인지 궁금합니다.

그리고 hostname의 뒤에서 3개의 문자를 잘라내기 위해 tail -c 4를 사용했는데, 왜 4를 넣어야 3개가 출력될까요? 예전에 자바 잠시 공부할 때 문자열 끝에 눈에 보이지는 않지만 문자열의 끝임을 나타내는 뭔가가 있다고 본 것 같은데 그거랑 관련이 있는건지 궁금하네요.

그리고 저처럼 리눅스를 처음 공부하시는 분들을 위해 한가지 알려드리자면
$(hostname | tail -c 4) 부분을 보면 $(명령어) 구조인데요, 동일한 역할을 `명령어` 도 합니다.
그래서 위 명령어를 아래와 같이 바꾸어도 무방합니다.

echo \!@#`hostname | tail -c 4`sbox | passwd --stdin root

그런데 저는 ` 기호보다 $괄호가 눈에 더 잘 들어오는 것 같습니다.


혹시 위 방법 외에 더 좋은 방법이 있다면 의견 주시면 고맙겠습니다.

요즘 회사에서 업무 특성상 윈도우 배치파일이나 리눅스 쉘스크립트를 짜야할 일이 많습니다. 아니 스크립트를 짜는게 업무는 아닌데, 단순 노가다 작업을 일일이 키보드로 입력하는게 싫어서 저는 웬만하면 스크립트로 만들려고 노력하고 있습니다. 워낙 바빠서 블로그 포스팅은 거의 못하고 있는데, 가끔씩 이렇게 배치파일이나 쉘스크립트에 대해 소개하도록 하겠습니다.
  1. BlogIcon KurenoCat
    2011.05.16 01:53

    Bash 스크립트에서 ! 문자는 NOT 을 의미합니다.
    자세한 건 bash 의 man 페이지를 보시면 될거예요.

    • BlogIcon snoopybox
      2011.05.16 02:08 신고
      수정 및 삭제

      답변 감사합니다. event not found가 나오길래 저는 무슨 event랑 관련있는건줄 알았는데 단순히 not이었군요. ^^

  2. CMD
    2011.05.16 06:38

    문자열의 끝임을 나타내는 것은 널문자('\0')입니다.

  3. intact
    2011.05.16 10:01

    bash에서 !는 이전 실행 했던 커맨드을 다시 실행하는 특수 문자입니다.
    history 라는 커맨드를 실행하면, 이전에 실행했던 커맨드들을 볼 수 있는데요.
    예를 들어, 이전 커맨드 이력중에 'ls -la' 라는 커맨드가 있다고 하고,
    $ !ls
    라는 커맨드을 내릴 경우, history에 있는 커맨드들중에 ls로 시작하는 가장 최근 커맨드를 다시 실행하라 라는 의미가 됩니다.

    다시 말해, 위 본문의 내용을 escape 하지 않은채 실행하게 되면,
    실행했던 커맨드중 @#`hostname로 시작하는 커맨드를 찾게 되는게, 그런 실행 이력이 없기 때문에, event not found 에러가 발생하게 됩니다.

  4. 프리네
    2011.05.16 10:25

    안녕하세요. 항상 좋은 정보 감사합니다. 컴생활이나 업무에 도움이 많이 되어 자주 들리는 편인데, 정식으로 인사를 드리는 것은 처음인듯 하네요. 항상 건강하시고 하시는 일들이 잘 되기를 응원할께요...^^

    아! 그리고 본문내용과는 맞지 않은듯 하지만 요즘 고민거리가 있어 마지막으로 스누피님께 조언 구해봅니다.
    윈도우7 얼티밋 64비트 사용하고 있는데요. 어느순간 제어판의 장치 및 프린터에 내용이 모두 사라지고 보이지 않습니다. 그래서인지 트레이에 뜨는 안전제거에도 내용이 보이지 않구요. 보이지만 않을뿐 장치관리자나 작동에는 문제가 없습니다. 개별적으로 확인해보면 모두 존재하거든요. 원래 프로 사용하다가 지난달 얼티밋으로 애니타임 업글을 했습니다. 레지정보를 건드린것인지...구글 검색으로 나름 알려진 방법은 다해보았는데 되지를 않네요.

    사용상에는 문제가 없으나 신경이 쓰이네요. 그렇다고 재설치는 엄두가 나지 않고요.

  5. BlogIcon 김.철.수
    2011.05.16 16:20 신고

    평소에 좋은 글 많이 읽기만 했던 사람입니다.
    혹시나 도움이 될까하여 댓글을 남겨봅니다.

    저라면 아래와 같이 스크립트로 작성해놓고 사용합니다.

    짧게 사용하자면 스누피님처럼 사용을 하겠지만 오퍼레이션 업무가 단순, 반복적인 작업이 많다보니
    아래와 같이 저장해놓고 인수인계 할 때도 스크립트 위주로 설명을 하고 있습니다.

    또한 외부명령어를 실행할 때 ` ` 문자를 더 자주 사용하게 됩니다. $ 문자는 변수명과 혼동이 될 수 있어
    되도록이면 사용을 자제하는 편입니다.

    --------------------------------------------

    #!/bin/bash

    # str1은 문자열 !@# 을 저장
    str1="!@#"

    # hostname 실행 결과문자열의 끝부분에서 3문자를 str2에 저장
    # (종료문자 \O를 계산하여 tail -c 3이 아닌 -4가 됩니다)
    str2=`hostname | tail -c 4`

    # str3은 문자열 sbox를 저장
    str3="sbox"

    # strHostname은 hostname 실행 결과 문자열 저장
    strHostname=`hostname`

    # $str1 대신 ${str1}을 적은 것은 구분이 쉽게 하기 위함입니다.
    # 만일 str1 변수값이 abc 이라 가정하고
    # str2 변수값이 xyz 이라 가정할때
    #
    # strPasswd 라는 변수에 abcDBxyz 이라는 문자열을 저장하고 싶은 경우
    # strPasswd="$str1DB$str2" 라고 표현하면 변수 str1인지 변수 str1DB 인지
    # 알수가 없는 문제가 발생합니다.
    # 또한 위와같이 표현하면 다른 개발자가 이해하기가 어렵습니다.
    #
    # 그래서 strPasswd="${str1}DB${str2}" 형식으로 변수명을 { } 문자로
    # 둘러쌓아서 표현하면 조금은 이해가 쉬워지기 때문입니다.
    #
    strPasswd="${str1}${str2}${str3}"

    echo "root@${strHostname}'s password=${strPasswd}"
    echo "${strPasswd}" | passwd --stdin root
    --------------------------------------------

    덧붙이자면 관리해야 하는 서버가 rcp, rsh, rlogin 등이 보안상 허용된다면 쉘스크립트만으로도 작업하는데
    큰 문제가 없지만 보안 특성상 SSH 만이 허용되는 경우 java 를 이용하시면 좋습니다.

    근래들어 농협, 현대카드 등의 보안문제가 이슈화 되어 ssh 사용에 있어 서버, 계정간 trust 계정 설정도
    굉장히 제한되고 있습니다.

    물론 약간의 공부에 대한 부담은 있습니다만 ssh 를 이용하여 계정 관리 정도의 프로그램은 스누피님의
    능력이라면 1개월 정도면 java 학습으로 충분히 만드실 것 같다는 생각이 듭니다.

    만일 관리하는 서버가 리눅스가 아닌 HP-UX, AIX, Solaris 등의 여러 OS인 경우 ssh 라이브러리를 이용한
    java 개발은 오퍼레이터 역할에서 더욱 필요하지 않을 까 생각됩니다.

    그럼 수고하세요. 항상 좋은 글 감사하게 생각하고 있습니다.

  6. BlogIcon hongyang
    2011.05.18 21:18

    글자가 보이지 않네요. 매일 따라하기만 해서 ㅠㅠ
    그런데 ! 유용하네요.

  7. BlogIcon TaeL
    2011.10.10 13:26

    !에 대해 많은 분이 댓글로 알려주셨군요. ㅎㅎ
    댓글 첫번째 NOT에 대한 의견은 잘 못 적용된 내용입니다.
    !의 의미는 대부분 NOT의 의미를 담고 있지만 여기서는 해당되지 않습니다 ^^;;
    bash의 Event Designators를 보면 아래와 같은 설명이 있습니다.
    ------------------------------------------------------------
    !string
    Refer to the most recent command starting with string.
    ('string'으로 시작하는 가장 최신의 명령을 참조한다.)
    ------------------------------------------------------------
    공식 문서 내용 참조:
    http://www.gnu.org/s/bash/manual/bash.html#Event-Designators


    추가:
    아래 링크의 내용에 싱글쿼트(')와 더블쿼트(")의 차이가 설명되어있습니다.

    링크의 요는, 스페셜캐릭터(이스케이프시퀀스)를 포함하는 문자열의 경우 싱글쿼트(')로 감싸게 되면 그 스페셜한 기능을 막아버립니다. strong quote라고 일컫는 부분이지요.
    다시말해서 echo '!@#'~~~~ 라고 사용하게 되면 해결될 문제라는 것입니다. 방법은 여러가지 있지만 참고하시면 좋겠네요.ㅎ

    링크:(공식문서아님)
    http://stream-recorder.com/forum/problem-bash-event-not-found-exclamation-between-t5456.html



    사용하시는 것을 보니 일회성으로 쓸 일이 아닌 것 같아 추가로 공부해 보시라고 부담 얹어드리고 갑니다. ㅎㅎ
    덕분에 공식문서 찾아보고 같이 공부할 수 있는 계기가 되었습니다.
    감사합니다.