설치 작업을 자동화하다 보면 중간중간 사용자 입력을 요구하는 대화형 스크립트를 만나게 됩니다. Chef 레시피 안에서 이런 입력까지 자동으로 처리하는 방법을 고민하다가, OS에서 제공하는 expect 명령어를 이용해 구현했습니다.
Chef 자체 리소스만으로 해결하는 방법을 먼저 찾고 싶었지만, 당시에는 적절한 방법을 찾지 못했습니다. 대화형 입력을 우회할 수 있는 별도 옵션이 스크립트에 있다면 그 방법을 우선 검토하는 것이 좋고, 그렇지 않을 때 expect를 활용할 수 있습니다.
아래 예는 JBoss의 add-user.sh 대화형 스크립트 실행을 Chef로 자동화한 것입니다.
대화형 실행 화면
< 화면 >
# ./add-user.sh What type of user do you wish to add? a) Management User (mgmt-users.properties) b) Application User (application-users.properties) (a): a Enter the details of the new user to add. Realm (ManagementRealm) : [엔터] Username : jbossadm Password : admin Re-enter Password : admin About to add user 'jbossadm' for realm 'ManagementRealm' Is this correct yes/no? yes Added user 'jbossadm' to file '/jboss/6.1.0/standalone/configuration/mgmt-users.properties' Added user 'jbossadm' to file '/jboss/6.1.0/domain/configuration/mgmt-users.properties' Is this new user going to be used for one AS process to connect to another AS process? e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls. yes/no? yes
Chef recipe 예시
< recipe >
bash "add-user.sh" do
user "#{node[:JBOSS][:USER][:NAME]}"
cwd "#{inst_home}"
code << -EOH
/usr/bin/expect -c 'spawn ./add-user.sh
expect "(a): "
send "a\n"
expect "Realm (ManagementRealm) : "
send "\n"
expect "Username : "
send "jbossadm\n"
expect "Password : "
send "admin\n"
expect "Re-enter Password : "
send "admin\n"
expect "Is this correct yes/no? "
send "yes\n"
expect "yes/no? "
send "yes\n"
expect eof'
EOH
end
적용할 때 확인할 점
expect는 화면에 출력되는 문자열을 기다렸다가 지정한 값을 입력하는 방식입니다. 따라서 스크립트의 프롬프트 문구가 버전이나 설정에 따라 달라지면 레시피가 멈출 수 있습니다. 적용 전에는 대상 서버에서 한 번 수동으로 실행해 실제 출력 문자열을 확인하고, Chef 실행 후에는 생성된 사용자 파일이나 설정 파일이 기대한 위치에 반영되었는지 확인하는 것이 좋습니다.
또한 예시처럼 비밀번호를 레시피에 직접 적으면 저장소나 로그를 통해 노출될 수 있습니다. 실제 운영 환경에서는 암호와 같은 민감 정보는 별도 관리 방식을 사용하는 것이 안전합니다.
사실 Chef 주제로 이야기했지만, 이 방식은 Chef에만 한정되지 않습니다. 일반 OS 셸 환경에서도 대화형 스크립트를 자동화해야 할 때 동일하게 활용할 수 있습니다.