CS(computer science)

linux [Dockerfile shell script]( nginx cofiguring for docker using sed command in shell in Dockerfile) sed 명령어로 특정 문자열 뒤의 모든 문자열 치환하기, 주석처리하기, 문자열 추가하기.

ebang 2023. 7. 4. 23:00

sed 명령어로 특정 문자열 뒤의 모든 문자열 치환하기, 주석처리하기, 문자열 추가하기. (feat. nginx config file 수정하기)

 

이 명령어를 찾게 된 맥락은 다음과 같다.

docker compose 를 이용해서 nginx, wordpress, mariadb 를 연동하려고 하는데 conf 파일의 수정이 불가피했다.

dockerfile 명령어 COPY를 이용해서 host의 미리 수정해둔 파일을 가져올 수 있기는 하다. 이미 있는 default 파일을 원하는 대로 수정하는 것이다. 

그러나 default conf 파일이 update 된 경우 작동이 잘 안될 수도 있다.

또한 이 파일을 어쩔 수 없이 git 에 올려야 하는 경우, WORDPRESS_AUTH_KEY 같은 값들이 노출 되기 떄문에 보안상 문제가 될 수 있다고 판단했다. 

 

https://api.wordpress.org/secret-key/1.1/salt/

위의 사이트에서는 자동으로 wordpress를 위한 auth관련된 키를 생성해준다. 

이 키를 받아와서 직접 conf 파일에 추가할 수 있도록 shell script를 작성했다.

 

이에 사용된 몇가지 sed 명령어를 소개한다. 

awk 등도 쓸 수 있지만 sed로 통일해봤다.

 

수정하고자 하는 conf 파일의 default 버전은 다음과 같다. 

 

 

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );

/** Database username */
define( 'DB_USER', 'username_here' );

/** Database password */
define( 'DB_PASSWORD', 'password_here' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
define( 'NONCE_SALT',       'put your unique phrase here' );

🌕문제상황 정리 define the problem🌕

1. 'database_name_here' 등과 같은 내용은 쉽게 갖고 있는 환경변수 값으로 대체가능하다. 

the phrases 'database_name_here' .. etc are easy to fix using sed command in shell.

 

2. 'put your unique phrase here' 의 내용은 중복될 뿐만아니라, 랜덤한 키 생성이 필요하다. 

'put your unique phrase here' has lots of locations, plus it needs to be generated randomly.

below the url provides a serivce to generate random key.

 

이러한 키 생성을 도와주는 api로 https://api.wordpress.org/secret-key/1.1/salt/ 라는 웹사이트가 존재한다. 

 

 

 

 

 

🌕몇가지 sed 명령어 정리

🌕1. 특정 문자열 뒤의 모든 문자열 치환하기

기존 문서 ./test.txt

define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );

 

 

sed 명령어 사용

sed -i "s/'database_name_here'/${WORDPRESS_DB_NAME}/g" ${WP_PATH}${WP_FILE}

 

 

 

 

결과 출력 : 

define( 'DB_NAME', '내가 설정한 ${WORDPRESS_DB_NAME}의 값' );

다음과 같이 출력된다. 

 

-i 옵션을 사용하면 실제 문서를 고치게 된다. 

 

 

 

만약 바꾸고자 하는 문자열이 경로나 특수문자가 포함된 경우에는

sed: -e expression #1, char 20: unknown option to `s' 와 같은 에러가 발생하기도 한다.

 

이런 경우에는 / (슬래시) 대신에 | (버티컬 바) 를 사용하면 된다!

 

 

 

🌕 2. 주석처리하기

sed -i 's/^문자열/#&/' 파일 경로

 

를 하면 된다.

 

 

 

cat www.conf 해서 나온 test.txt 의 아래 문자열을 주석처리 하고 싶다. 

listen = /var/run/php5-fpm.sock

 

 

  • -i: sed 명령어가 파일을 직접 수정하도록 지정한다.
  • s/: 패턴 대체를 시작한다.
  • ^문자열: 주석 처리할 특정 문자열을 나타낸다. 이 예제에서는 문자열을 실제 주석 처리할 문자열로 바꿔야 한다.
  • /#&/: 찾은 패턴을 주석 처리한다. #은 주석 기호이며, &는 일치한 문자열 전체를 의미한다.
  • 파일명: 주석 처리를 적용할 파일의 이름이다. 

 

다음과 같이 명령어를 실행하면 된다.

 

sed - i 's|^listen = /var/run/php5-fpm.sock|#&/' ${WWW_CONF_PATH}${WWW_CONF_FILE}

(경로에도 '/'가 있기 때문에 '/'대신 '|'을 사용했다. 대신 이스케이프 문자 '\' 를 사용하는 것도 가능하다. )

 

그럼 다음과 같이 변한다. 

#listen = /var/run/php5-fpm.sock

 

 

🌕3. 특정 문자열 아래에 문자열 추가하기. 

sed '주소a\추가할 문자열' 파일명

a: sed 명령어에 대해 "append"를 나타내며, 주어진 주소 아래에 텍스트를 추가한다. 

 

🌕4. 특정 문자열들을 모두 삭제하고, 그 위치에 원하는 문자열을 추가하기.

define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
define( 'NONCE_SALT',       'put your unique phrase here' );

위의 값들을 모두 지우고 그 위치에 아래 링크에서 주는 

https://api.wordpress.org/secret-key/1.1/salt/
define('AUTH_KEY',         'EjDYv*6~;6=-QcN/H(4F^U|-|sk<vTVs~E^sj>*X#@R64<>+n,-0L/xp+E6x3-!~');
define('SECURE_AUTH_KEY',  'o!ZbV5Zz|9-An^g%Pw+z#Cx.|yYS[LeNwEjTj@7K*SR.6|GJ[hPVYW.BWnz[SE,|');
define('LOGGED_IN_KEY',    'tmq)Cv5CDZxE%+EEG9Qn+bZ4{sfeV]L{ZbF9-bd/I4Zk`1,+pY4:|WjSh5=T,Q 4');
define('NONCE_KEY',        ' >r_T0X{*o{ie>9&}P7caq%BJA0a0KA 8JMy|ys-s^L]XV+Vm1a{eO,||Q%`RB5Q');
define('AUTH_SALT',        '^L{3Jz6.wf+SVMsbj&?Krx:p3tg4GNgPcV^:j;hGq4W`2PQ6EP,]d&RwL8&DbfhF');
define('SECURE_AUTH_SALT', 'I,v;:BJ6|u$qK,WYj!w0Nqm;$|%CRvJ:-2>;2mS]@;Jk1C^~6;;+aFD^qhMh+x4M');
define('LOGGED_IN_SALT',   'C`$t[=S+^%4CcCku>&Rcj/Wx;,R-?qF1<{/YFJ:XJNCMO^GHHZi5wkaI=M,qj&s$');
define('NONCE_SALT',       'CQnBR$pMW5sK}<FzyA~+}Mn3wT<ZLpiAw7pE@0?}`3XFckWSFp_t+6-PO%+W fGJ');

이런 스트링으로 대체할 것이다. 

 

SALT=$(curl -L https://api.wordpress.org/secret-key/1.1/salt/) #SALT 변수에 모두 담아온다.
STRING='put your unique phrase here' #찾고 삭제할 부분
grep -n ${STRING} ${WP_PATH}${WP_FILE}| cut -d ':' -f 1 | tail -n 1 | \
xargs -I  {} sed '{}s/.*/new line/g' ${WP_PATH}${WP_FILE}

grep -n 으로 찾고자 하는 STRING의 행을 출력하고, 그 중 행만을 뽑기 위해 cut, tail을 한다.

grep 만 쓰면 

2:define( 'AUTH_KEY',         'put your unique phrase here' );
3:define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
4:define( 'LOGGED_IN_KEY',    'put your unique phrase here' );

이런식으로 출력되기 때문에 ':'을 기준으로 이전 문자열만을 남기고, 또 그 중에서 마지막 행만을 남겨둔다.

그 값을 xargs 를 이용해서 sed의 인자로 넘겨준다.

sed -i 'N;s/pattern/replacement/' filename

다음 명령어는 N줄의 pattern 문자열을 replacement 문자열로 filed을 변경하는 명령어이다. 

xargs를 이용해서 {}안에 찾은 행의 값을 전달하고, 행 전체를 바꿀 거라서 .*을 사용한다. 

이렇게 하고 나면 결과는 다음과 같아진다. 

...
define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
new line
...

마지막 행에 new line이 추가된다. 

 

new line 대신 ${SALT} 를 넣어서 실행하면 원하는 문자열들이 모두 삽입될 것이고, 

 

마지막으로

sed -i '/patternToDelete/d' filename

삭제하는 위 명령어로 지워주면 된다.

 

 

 

(이면 될 줄 알았는데... SALT 안의 내용이 특수문자가 많아서 문제가 되었다. )

다시 고친 내용은 다음과 같다. 

고치려고 하는 파일이 test.txt 이고 'put your unique phrase' 행이 담긴 문자열은 모두 지우고 그 위치에 url이 주는 문자열로 바꾸려는 시도이다. 

 

🌕문제상황 해결 solve🌕

<Trial to fix 'put your unique phrase here' to the string that the url below gives>

https://api.wordpress.org/secret-key/1.1/salt/

SALT=$(curl -L https://api.wordpress.org/secret-key/1.1/salt/)
STRING="put your unique phrase here"

echo "${SALT}" > temp.txt

grep -n "${STRING}" ${WP_PATH}${WP_FILE} | cut -d ':' -f 1 | tail -n 1 | \
xargs -I {} sh -c 'sed -i "{}r temp.txt" ${WP_PATH}${WP_FILE}'
echo $STRING | xargs -I {} sh -c 'sed -i "/{}/d" ${WP_PATH}${WP_FILE}'

 

이렇게 하면 완성... ⭐️