echo 명령에 대한 실행 추적을 억제 하시겠습니까?


29

Jenkins에서 쉘 스크립트를 실행 중이며 shebang 옵션으로 쉘 스크립트를 시작합니다 #!/bin/sh -ex.

인형에 대한 Bash Shebang에 따르면 ? ,, -x"셸이 실행 추적을 인쇄하도록합니다"는 에코를 제외하고 대부분의 목적에 적합합니다.

echo "Message"

출력을 생성

+ echo "Message"
Message

이것은 약간 중복적이고 약간 이상하게 보입니다. -x활성화 상태로 두는 방법이 있습니까?

Message

위의 두 줄 대신, 예를 들어 echo 명령 앞에 특수 명령 문자를 붙이거나 출력을 리디렉션하면?

답변:


20

악어의 목에 달렸을 때, 목표는 늪을 배수하는 것임을 잊기 쉽습니다.                   — 인기있는 말

문제는에 관한 echo것이지만 지금까지 대부분의 답변은 set +x명령 을 몰래 넣는 방법에 중점을 두었 습니다. 훨씬 간단하고 직접적인 해결책이 있습니다.

{ echo "Message"; } 2> /dev/null

(나는 { …; } 2> /dev/null 이전 답변에서 그것을 보지 못했다면 생각하지 않았을 수도 있음을 인정합니다 .)

이 작업은 다소 번거롭지 만 연속 된 echo명령 블록이있는 경우 각 명령을 개별적으로 수행 할 필요가 없습니다.

{
  echo "The quick brown fox"
  echo "jumps over the lazy dog."
} 2> /dev/null

줄 바꿈이있을 때는 세미콜론이 필요하지 않습니다.

비표준 파일 디스크립터 (예 : 3)를 영구적으로 열고 항상 대신 말하는 kenorb의 아이디어 를 사용하여 입력 부담을 줄일 수 있습니다 ./dev/null2>&32> /dev/null


이 글을 쓰는 시점에서 처음 네 대답은 (대부분의 경우, 성가신에, 등) 뭔가 특별한 일을 필요로 모든 당신이 할 시간 echo. 모든 echo 명령이 실행 추적을 억제하기 를 정말로 원한다면 (그리고 왜 그렇지 않을까요?) 많은 코드를 문지르지 않고도 전체적으로 그렇게 할 수 있습니다. 먼저 별칭이 추적되지 않는 것으로 나타났습니다.

$ myfunc()
> {
>     date
> }
$ alias myalias="date"
$ set -x
$ date
+ date
Mon, Oct 31, 2016  0:00:00 AM           # Happy Halloween!
$ myfunc
+ myfunc                                # Note that function call is traced.
+ date
Mon, Oct 31, 2016  0:00:01 AM
$ myalias
+ date                                  # Note that it doesn’t say  + myalias
Mon, Oct 31, 2016  0:00:02 AM

(다음 스크립트 스 니펫 은 bash에 대한 링크 인 #!/bin/sh경우에도 shebang이 작동하면 작동 /bin/sh하지만 shebang이 #!/bin/bash인 경우 shopt -s expand_aliases스크립트에서 별명이 작동하도록 명령을 추가해야합니다 .)

그래서 첫 번째 트릭은 다음과 같습니다.

alias echo='{ set +x; } 2> /dev/null; builtin echo'

이제 우리가 말할 때 echo "Message"추적되지 않는 별칭을 호출합니다. 별명은 추적 옵션을 끄고 set명령 에서 추적 메시지를 억제하고 ( user5071535의 answer 에서 처음 제시된 기술 사용 ) 실제 echo명령 을 실행합니다 . 이를 통해 모든 echo 명령 에서 코드를 편집 할 필요없이 user5071535의 답변과 유사한 효과를 얻을 수 있습니다 . 그러나 이렇게하면 추적 모드가 해제됩니다. set -x별칭은 문자열을 단어로만 대체 할 수 있기 때문에 별칭에 (또는 최소한 쉽지 는 않습니다) 넣을 수 없습니다 . 인수 뒤에 별칭 문자열의 어떤 부분도 명령에 삽입 할 수 없습니다 (예 :) "Message". 예를 들어 스크립트에

date
echo "The quick brown fox"
echo "jumps over the lazy dog."
date

출력은

+ date
Mon, Oct 31, 2016  0:00:03 AM
The quick brown fox
jumps over the lazy dog.
Mon, Oct 31, 2016  0:00:04 AM           # Note that it doesn’t say  + date

따라서 메시지를 표시 한 후에도 추적 옵션을 다시 설정해야하지만 연속 된 모든 명령 블록 마다 한 번 씩만 echo수행해야합니다.

date
echo "The quick brown fox"
echo "jumps over the lazy dog."
set -x
date


우리가 set -x자동으로 할 수 있다면 더 좋을 것echo 입니다. 그러나 그것을 제시하기 전에 이것을 고려하십시오. OP는 #!/bin/sh -exshebang 을 사용하는 스크립트로 시작 합니다. 암시 적으로 사용자 x는 shebang에서를 제거하고 실행 추적없이 정상적으로 작동하는 스크립트를 가질 수 있습니다. 해당 속성을 유지하는 솔루션을 개발할 수 있다면 좋을 것입니다. 여기의 처음 몇 가지 대답은 속성 echo이 이미 켜져 있는지 여부에 관계없이 after 문을 무조건적 으로 추적하기 때문에 해당 속성에 실패합니다 .  이 답변은 눈에 띄게 그것으로, 그 문제를 인식하지 못합니다 대체 echo추적 출력으로 출력; 따라서 추적이 해제되면 모든 메시지가 사라집니다. 이제 echo문장이 끝난 후에 만 조건부로 추적을 다시 켜는 솔루션을 제시하겠습니다 . 무조건 추적을 "뒤로"돌리는 솔루션으로 이것을 다운 그레이드하는 것은 쉽지 않으며 연습으로 남겨집니다.

alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
echo_and_restore() {
        builtin echo "$*"
        case "$save_flags" in
         (*x*)  set -x
        esac
}

$-옵션 목록입니다. 설정된 모든 옵션에 해당하는 문자의 연결. 예를 들어, ex옵션이 설정되어, 다음 $-포함 문자의 뒤범벅이 될 것입니다 ex. 위의 새 별칭은 $-추적 기능을 끄기 전에 의 값을 저장합니다 . 그런 다음 추적을 끄면 제어를 쉘 기능으로 넘깁니다. 이 함수는 실제 작업 echo 을 수행 한 다음 x별명이 호출 될 때 옵션이 켜져 있는지 확인합니다 . 옵션이 켜져 있으면 기능이 다시 켜집니다. 꺼져 있으면 기능이 꺼져 있습니다.

shopt스크립트 시작 부분에 위의 7 줄 (을 포함하면 8 개)을 삽입 하고 나머지는 그대로 둡니다.

이것은 당신을 허용 할 것입니다

  1. 다음 shebang 라인 중 하나를 사용하십시오.
    #! / bin / sh -ex
    #! / bin / sh -e
    #! / bin / sh –x
    아니면 그냥 평범한
    #! / bin / sh
    예상대로 작동합니다.
  2. 같은 코드를 가지고
    (shebang) 
    명령 1
     명령 2
     명령 3
    세트 -x
    명령 4
     명령 5
     명령 6
    + x 설정
    명령 7
     명령 8
     명령 9
    • 명령 4, 5 및 6은 추적됩니다. 명령 중 하나가이 아닌 echo경우에는 실행되지만 추적되지는 않습니다. (그러나 명령 5가 echo이지만 명령 6은 여전히 ​​추적됩니다.)
    • 명령 7, 8 및 9는 추적되지 않습니다. 명령 8이 echo이지만 명령 9는 여전히 추적되지 않습니다.
    • 명령 1, 2 및 3은 shebang의 포함 여부에 따라 추적 (4, 5 및 6과 같은) 또는 7, 7, 8 및 9와 같은 추적되지 않습니다 x.

추신 : 나는 내 시스템에서 builtin키워드를 중간 답변 (의 별명 인 키워드)에서 제외 할 수 있음을 발견했습니다 echo. 이것은 놀라운 일이 아닙니다. bash (1)은 별칭 확장 중에…

… 확장중인 별칭과 동일한 단어는 두 번 확장되지 않습니다. 이것은 예를 들어 별칭 ls을 지정할 수 ls -F있으며 bash는 대체 텍스트를 재귀 적으로 확장하려고 시도하지 않습니다.

너무 놀라운 일이 마지막 대답 (로 한 echo_and_restore경우 생성)에 실패 builtin키워드가 생략 1 . 그러나 이상을 삭제 builtin하고 순서를 전환 하면 이상하게 작동합니다 .

echo_and_restore() {
        echo "$*"
        case "$save_flags" in
         (*x*)  set -x
        esac
}
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'

__________
1  정의되지 않은 행동을 일으키는 것 같습니다. 나는 본 적이

  • 무한 루프 (아마도 무한한 재귀로 인해)
  • /dev/null: Bad address오류 메시지 및
  • 코어 덤프.

2
나는 별칭으로 수행 된 놀라운 마술을 보았으므로 그 지식이 불완전하다는 것을 알고 있습니다. 누구든지 echo +x; echo "$*"; echo -x별칭으로 동등한 방법을 제시 할 수 있다면 그것을보고 싶습니다.
G-남자 '는 분석 재개 모니카'말한다

11

InformIT 에서 부분 솔루션을 찾았습니다 .

#!/bin/bash -ex
set +x; 
echo "shell tracing is disabled here"; set -x;
echo "but is enabled here"

출력

set +x; 
shell tracing is disabled here 
+ echo "but is enabled here"
but is enabled here

불행히도, 여전히 여전히 에코하지만, 그 set +x후에는 조용합니다. 적어도 문제에 대한 부분적인 해결책입니다.

그러나이 작업을 수행하는 더 좋은 방법이 있습니까? :)


2

이 방법은 set +x출력을 제거하여 자체 솔루션을 향상시킵니다 .

#!/bin/bash -ex
{ set +x; } 2>/dev/null
echo "shell tracing is disabled here"; set -x;
echo "but is enabled here"

2

set +x대괄호 안에 넣으면 로컬 범위에만 적용됩니다.

예를 들면 다음과 같습니다.

#!/bin/bash -x
exec 3<> /dev/null
(echo foo1 $(set +x)) 2>&3
($(set +x) echo foo2) 2>&3
( set +x; echo foo3 ) 2>&3
true

출력 :

$ ./foo.sh 
+ exec
foo1
foo2
foo3
+ true

내가 틀렸다면 나를 수정하지만 set +x서브 쉘 내부 (또는 서브 쉘을 전혀 사용 하지 않음 )가 유용한 것을하고 있다고 생각하지 않습니다 . 당신은 그것을 제거하고 동일한 결과를 얻을 수 있습니다. 일시적으로 "비활성화"추적 작업을 수행하는 것은 / dev / null로 리디렉션하는 stderr echo foo1 2>/dev/null입니다.
Tyler Rick

스크립트를 추적하면 성능에 영향을 줄 수 있습니다. 둘째로 & 2를 NULL로 경로 재지 정하는 것은 다른 오류가 예상 될 때 동일하지 않을 수 있습니다.
kenorb

내가 틀렸다면 나를 수정하십시오. 그러나 귀하의 예제에서 이미 스크립트를 사용하여 ( bash -x) 을 추적 하고 이미 &2null &3로 리디렉션하고 있기 때문에 (null 로 리디렉션되었으므로) 해당 주석이 어떻게 관련되어 있는지 잘 모르겠습니다. 어쩌면 우리는 요점을 보여주는 더 좋은 예가 필요할 수도 있지만, 주어진 예에서 적어도 이점을 잃지 않고 단순화 할 수있는 것처럼 보입니다.
Tyler Rick

1

나는 g-man 의 포괄적이고 잘 설명 된 답변을 좋아하며 지금까지 제공된 최고의 답변 이라고 생각합니다. 스크립트의 컨텍스트에 관심이 있으며 필요하지 않은 경우 강제로 구성하지 않습니다. 따라서이 답변을 먼저 읽고 있다면 그 장점을 모두 확인하십시오.

그러나 그 대답에는 중요한 부분이 빠져 있습니다. 제안 된 방법은 일반적인 사용 사례에서는 작동하지 않습니다 (예 : 오류보고).

COMMAND || echo "Command failed!"

별칭이 구성되는 방식으로 인해

COMMAND || { save_flags="$-"; set +x; } 2>/dev/null; echo_and_restore "Command failed!"

그리고 당신은 그것을 추측하고 무조건적으로 항상echo_and_restore 실행 됩니다. 점을 감안 부분이 실행되지 않은, 그 함수의 내용도 인쇄되는 것을 의미합니다.set +x

마지막으로 변경 ;하기 &&때문에 배쉬에서 어느 작동하지 않을 ||하고 &&있습니다 왼쪽 연관 .

이 사용 사례에 맞는 수정을 찾았습니다.

echo_and_restore() {
    echo "$(cat -)"
    case "$save_flags" in
        (*x*) set -x
    esac
}
alias echo='({ save_flags="$-"; set +x; } 2>/dev/null; echo_and_restore) <<<'

(...)모든 명령을 그룹화하기 위해 서브 쉘 ( 부분) 을 사용한 다음 stdin 을 통해 입력 문자열을 Here String ( <<<사물) 로 전달한 다음에 의해 인쇄됩니다 cat -. 은 -선택 사항이지만, 당신은 "알고 명시 적 암시보다 낫다 ".

echocat - 없이 직접 사용할 수도 있지만 다른 문자열을 출력에 추가 할 수 있기 때문에이 방법이 마음에 듭니다. 예를 들어 다음과 같이 사용하는 경향이 있습니다.

BASENAME="$(basename "$0")"  # Complete file name
...
echo "[${BASENAME}] $(cat -)"

이제는 아름답게 작동합니다.

false || echo "Command failed"
> [test.sh] Command failed

0

실행 추적은로 이동하여 다음 stderr과 같이 필터링합니다.

./script.sh 2> >(grep -v "^+ echo " >&2)

단계별 설명 :

  • stderr 리디렉션됩니다… – 2>
  • … 명령에. –>(…)
  • grep 명령입니다 ...
  • … 줄의 시작이 필요합니다… – – ^
  • … 다음에 + echo
  • … 그런 다음 grep경기 를 뒤집습니다… –-v
  • … 원하지 않는 모든 줄을 버립니다.
  • 결과는 일반적으로 stdout; 우리 stderr는 그것이 속한 곳으로 리디렉션합니다 . –>&2

문제는이 솔루션이 스트림을 비 동기화 할 수 있다는 것입니다. 필터링으로 인해 ( 출력이 기본적으로 속하는) stderr관련하여 약간 늦을 수 있습니다 . 이 문제를 해결하려면 스트림을 둘 다 가지고 있지 않아도 먼저 스트림에 참여할 수 있습니다 .stdoutechostdout

./script.sh > >(grep -v "^+ echo ") 2>&1

이러한 필터링을 스크립트 자체에 빌드 할 수는 있지만 이 방법은 비동기 화가 발생 하기 쉽습니다 (예 : 테스트에서 발생했습니다 : 명령의 실행 추적이 바로 다음 출력 후 나타날 수 있음 echo).

코드는 다음과 같습니다.

#!/bin/bash -x

{
 # original script here
 # …
} 2> >(grep -v "^+ echo " >&2)

트릭없이 실행하십시오.

./script.sh

다시 > >(grep -v "^+ echo ") 2>&1스트림을 조인하는 비용으로 동기화를 유지하는 데 사용 하십시오.


다른 접근법. 당신은 당신의 터미널 믹스 때문에 "비트 중복"이상한 보이는 출력을 얻을 stdout하고stderr . 이 두 개 시내는 이유가 다른 동물입니다. 분석이 stderr귀하의 요구에만 맞는지 확인하십시오 . 폐기 stdout:

./script.sh > /dev/null

스크립트에 echo인쇄 디버그 / 오류 메시지가있는 stderr경우 위에서 설명한 방식으로 중복성을 제거 할 수 있습니다. 전체 명령 :

./script.sh > /dev/null 2> >(grep -v "^+ echo " >&2)

이번에는 우리 만 작업 stderr하므로 비 동기화는 더 이상 문제가되지 않습니다. 불행히도이 방법으로 echo인쇄물 의 흔적이나 출력을 볼 수 없습니다 stdout(있는 경우). 우리는 리디렉션 (감지하기 위해 필터를 다시 시도 할 수 있습니다 >&2)하지만 당신은 보면 echo foobar >&2, echo >&2 foobar그리고 echo "foobar >&2"당신은 그 일이 복잡 아마 동의 할 것이다.

스크립트에 포함 된 에코에 따라 달라집니다. 복잡한 필터를 구현하기 전에 두 번 생각하면 역효과가 발생할 수 있습니다. 중요한 정보를 실수로 놓치는 것보다 약간의 중복성을 갖는 것이 좋습니다.


실행 추적을 버리는 대신 echo출력과 추적을 제외한 모든 출력을 버릴 수 있습니다. 실행 추적 만 분석하려면 다음을 시도하십시오.

./script.sh > /dev/null 2> >(grep "^+ " >&2)

바보 야? 아니요 echo "+ rm -rf --no-preserve-root /" >&2. 스크립트에 있으면 어떻게 될지 생각해보세요 . 누군가 심장 마비를 일으킬 수 있습니다.


그리고 마지막으로…

다행히 BASH_XTRACEFD환경 변수 가 있습니다. 보낸 사람 man bash:

BASH_XTRACEFD
유효한 파일 디스크립터에 해당하는 정수로 설정된 경우, bash는 set -x해당 파일 디스크립터에 대해 사용 가능할 때 생성 된 추적 출력을 기록합니다 .

다음과 같이 사용할 수 있습니다 :

(exec 3>trace.txt; BASH_XTRACEFD=3 ./script.sh)
less trace.txt

첫 번째 줄은 서브 쉘을 생성합니다. 이런 식으로 파일 디스크립터는 유효하지 않으며 현재 쉘에 지정된 변수는 나중에 유지되지 않습니다.

덕분 BASH_XTRACEFD에 에코 및 기타 출력이없는 트레이스를 분석 할 수 있습니다. 그것은 정확히 당신이 원하는 것이 아니지만 내 분석에 따르면 이것이 (일반적으로) 올바른 방법이라고 생각합니다.

물론 다른 방법을 사용할 수 있습니다. 특히 트레이스 를 분석 stdout및 / 또는 stderr추적 해야 할 때 . 특정 한계와 함정이 있다는 것을 기억하면됩니다. 나는 그들 중 일부를 보여 주려고 노력했다.


0

Makefile에서 @심볼을 사용할 수 있습니다 .

사용법 예 : @echo 'message'

에서 GNU의 문서 :

줄이 '@'로 시작하면 해당 줄의 에코가 억제됩니다. 행이 쉘로 전달되기 전에 '@'이 삭제됩니다. 일반적으로 make 파일을 통한 진행률을 나타내는 echo 명령과 같은 것을 인쇄하는 효과가있는 명령에이 기능을 사용합니다.


안녕하세요, 참조하는 문서는 쉘이 아닌 gnu make 용입니다. 확실하게 작동합니까? 오류가 발생 ./test.sh: line 1: @echo: command not found하지만 bash를 사용하고 있습니다.

와우, 죄송합니다. 질문을 완전히 잘못 읽었습니다. 예, @makefile에서 에코 할 때만 작동합니다.
데릭

@derek 원래 답변을 편집 했으므로 이제 솔루션이 Makefile에만 제한되어 있음을 분명히 나타냅니다. 나는 실제로 이것을 찾고 있었기 때문에 귀하의 의견이 부정적인 평판을 갖지 않기를 원했습니다. 잘만되면 사람들도 도움이 될 것입니다.
Shakaron

-1

중재자에 따라 2016 년 10 월 29 일에 원본에 무슨 일이 일어나고 있는지 이해하기에 충분한 정보가 포함되어 있지 않다고 제안되어 있습니다.

이 "트릭"은 xtrace가 활성화 된 경우 터미널에서 한 줄의 메시지 출력을 생성합니다.

원래 질문은 -x를 활성화 상태로 두는 대신 두 줄 대신 메시지 만 출력하는 것입니다 . 이것은 질문에서 정확한 인용입니다.

"set -x enabled 상태로두고 한 줄의 메시지를 생성하는 방법"이라는 질문을 이해하고 있습니까?

  • 세계적인 의미에서이 질문은 기본적으로 미학에 관한 것입니다 . 질문자는 xtrace가 활성화 된 상태에서 생성 두 개의 사실상 중복 되는 대신 단일 줄생성 하려고합니다 .

따라서 요약하면 OP에는 다음이 필요합니다.

  1. -x설정 하려면
  2. 사람이 읽을 수있는 메시지 작성
  3. 한 줄의 메시지 출력 만 생성합니다.

OP에서는 echo 명령을 사용할 필요 가 없습니다 . 그들은 예를 들어 라틴어 들어 라틴어 예를 들어 "약자"를 나타내는 약어를 사용하여 메시지 작성 의 로서 인용했다 .

"상자 밖에서"생각하고 메시지를 생성하기 위해 에코 를 사용하는 것을 포기 하면 할당 문이 모든 요구 사항을 충족시킬 수 있습니다.

메시지를 포함하는 텍스트 문자열을 비활성 변수에 지정하십시오.

스크립트에이 행을 추가해도 로직이 변경되지 않지만 추적이 활성화 될 때 단일 행이 생성됩니다 ( $ echo 변수를 사용하는 경우 이름을 사용되지 않은 다른 변수로 변경하십시오)

echo="====================== Divider line ================="

터미널에서 볼 수있는 것은 단 한 줄입니다.

++ echo='====================== Divider line ================='

OP가 싫어하는 두 가지가 아닙니다.

+ echo '====================== Divider line ================='
====================== Divider line =================

다음은 시연 할 샘플 스크립트입니다. 메시지로의 변수 대체 (끝에서 $ HOME 디렉토리 이름 4 행)가 작동하므로이 방법을 사용하여 변수를 추적 할 수 있습니다.

#!/bin/bash -exu
#
#  Example Script showing how, with trace active, messages can be produced
#  without producing two virtually duplicate line on the terminal as echo does.
#
dummy="====================== Entering Test Script ================="
if [[ $PWD == $HOME ]];  then
  dummy="*** "
  dummy="*** Working in home directory!"
  dummy="*** "
  ls -la *.c || :
else
  dummy="---- C Files in current directory"
  ls -la *.c || :
  dummy="----. C Files in Home directory "$HOME
  ls -la  $HOME/*.c || :
fi

그리고 루트에서 실행 한 다음 홈 디렉토리에서 실행 한 결과입니다.

$ cd /&&DemoScript
+ dummy='====================== Entering Test Script ================='
+ [[ / == /g/GNU-GCC/home/user ]]
+ dummy='---- C Files in current directory'
+ ls -la '*.c'
ls: *.c: No such file or directory
+ :
+ dummy='----. C Files in Home directory /g/GNU-GCC/home/user'
+ ls -la /g/GNU-GCC/home/user/HelloWorld.c /g/GNU-GCC/home/user/hw.c
-rw-r--r-- 1 user Administrators 73 Oct 10 22:21 /g/GNU-GCC/home/user/HelloWorld.c
-rw-r--r-- 1 user Administrators 73 Oct 10 22:21 /g/GNU-GCC/home/user/hw.c
+ dummy=---------------------------------

$ cd ~&&DemoScript
+ dummy='====================== Entering Test Script ================='
+ [[ /g/GNU-GCC/home/user == /g/GNU-GCC/home/user ]]
+ dummy='*** '
+ dummy='*** Working in home directory!'
+ dummy='*** '
+ ls -la HelloWorld.c hw.c
-rw-r--r-- 1 user Administrators 73 Oct 10 22:21 HelloWorld.c
-rw-r--r-- 1 user Administrators 73 Oct 10 22:21 hw.c
+ dummy=---------------------------------

1
삭제 된 답변의 편집 된 버전 (이것은 사본 임)도 OP가 요청한 관련 echo 명령없이 메시지 만 출력하지 않기 때문에 여전히 질문에 대답하지 않습니다.
DavidPostill


@David 메타 포럼의 의견에 따라 설명을 확대했습니다.
HiTechHiTouch

@David 다시 한 번 라틴어 ".eg"에주의하면서 OP를주의 깊게 읽어 보시기 바랍니다. 포스터에는 echo 명령을 사용할 필요가 없습니다. OP 는 문제를 해결하기위한 잠재적 인 방법 의 예제 로만 에코를 참조 합니다. 당신이 알고 보니이 하나 필요하지 않습니다
HiTechHiTouch

OP가 다음과 같은 일을하고 싶다면 echo "Here are the files in this directory:" *어떻게 해야 할까요?
G-Man, 'Reinstate
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.