명령줄 인수 내에서 환경 변수가 확장되지 않았습니다.

명령줄 인수 내에서 환경 변수가 확장되지 않았습니다.

user-pid.out2두 개의 열로 "usernumber"와 "process id"가 있는 파일이 있습니다 . 사용자 번호를 기반으로 해당 프로세스 ID를 찾고 싶습니다. 아래의 처음 두 줄에는 올바른 출력이 표시되지 않지만 줄 3과 4에서 사용자를 62로 하드코딩하면 사용자 62에 해당하는 프로세스 ID가 표시됩니다. 누군가 도와주실 수 있나요?

USR=62
usrpid=`awk '$1 == "$USR" {print $2}' /home/hu/batchhu/dbscripts_tst2/user-pid.out2`
echo "first:" $USR $usrpid
# This shows 62 and blank for process id

usrpid=`awk '$1 == "62" {print $2}' /home/hu/batchhu/dbscripts_tst2/user-pid.out2`
echo  "second:" $USR $usrpid
# This shows 62 and process id corresponding to this user in the file user-pid.out2

답변1

@artm은 awk 스크립트를 큰따옴표로 묶고 다양한 문자를 이스케이프 처리하는 기술을 보여주었습니다. 여기에 3가지 다른 기술이 있습니다.

쉘이 변수를 확장할 수 있도록 작은따옴표를 분리합니다.

usrpid=$(awk '$1 == "'"$USR"'" {print $2}' file)

쉘 변수를 awk 변수에 전달하십시오.

usrpid=$(awk -v usr="$USR" '$1 == usr {print $2}' file)

변수를 내보내는 경우 awk의 ENVIRON 배열을 사용하십시오.

usrpid=$(awk '$1 == ENVIRON["USR"] {print $2}' file)

후자를 선호해야 합니다.

@artm의 접근 방식과 같은 첫 번째 접근 방식에서는 쉘 변수의 내용이 awk코드 내부에 내장되어 있습니다.명령 주입 취약점변수의 내용이 엄격하게 제어되지 않는 경우(예를 들어 USR='blah" || system("reboot") || "'를 사용하면 을 호출함 reboot)

두 번째는 명령 주입 취약점을 일으키지 않지만 $USR백슬래시 문자가 포함된 경우 변수는 C와 유사한 백슬래시 이스케이프 시퀀스를 확장하므로 쉘 변수 usr awk와 동일한 것을 포함하지 않습니다 .$USRawk

사용에는 ENVIRON이러한 문제가 없습니다.

답변2

첫 번째 예 "$USR"에서는 작은따옴표로 묶인 문자열 내부에 발생하기 때문에 확장되지 않습니다 '$1 == "$USR" { print $2 }'. 따라서 이 코드는 첫 번째 열이 62가 아닌 "$USR"인 행을 찾습니다.

다음이 작동합니다.

usrpid=$(awk "\$1 == \"$USR\" {print \$2}" /home/hu/batchhu/dbscripts_tst2/user-pid.out2)

변경사항:

  1. awk 명령줄은 큰따옴표를 사용하므로 $USR이 확장됩니다.
  2. awk 프로그램 내의 달러 기호와 따옴표 문자는 이스케이프됩니다.
  3. $()백틱 대신 사용되므로백슬래시가 올바르게 처리되었습니다.

의 값은 USRawk 스크립트에 직접 삽입되므로 해당 값에 awk가 문자 그대로 해석할 문자만 포함된 경우에만 작동합니다. 또는 을 $USR포함 하면 모든 지옥이 풀릴 것입니다.  awk 문자열 리터럴의 끝이 됩니다. 다음 문자를 인용합니다 .\""\

관련 정보