ps 명령 역할을 하고 표시하려는 자체 속성을 사용하는 스크립트를 만들려고 합니다. ps 명령에서 프로세스가 다음과 같다고 가정합니다.
sas 24431 1 0 Oct10 ? 00:51:08 /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs
나는 이것을 다음과 같이 표시하고 싶다.
UID PID APPNAME
sas 24431 -Dapp.name=myApp
sas 24432 -Dapp.name=myApp2
sas 24433 -Dapp.name=myApp3
노트:이 app.name
속성은 ps 명령에서 추출된 명령 매개변수입니다.
이것은 내 스크립트입니다.
echo -e "PID\tUSERID\t\tAPPNAME"
ps -u $USER -f |grep "java"|grep -v "grep"|
while read LINE
do
#Get pid from the line
PID=$(cut -d" " -f2 <<< $LINE);
#Get parameter value called "-Dapp.name or -DprojectName"
#from the ps command for the process
APPNAME=$(ps -f $PID | awk 'BEGIN {RS=" "}; /-Dapp.name|-DprojectName/');
USERID=$(cut -d" " -f1 <<< $LINE);
echo -e $PID"\t"$USERID"\t"$APPNAME;
done;
이제 내가 원하는 방식으로 작동합니다. 하지만 가끔 정렬이 엉망이 되는 경우도 있습니다. 또한 이 스크립트를 한 줄 명령으로 최적화할 수 있습니까?
어떤 도움이라도 대단히 감사하겠습니다.
답변1
일반적인 테이블 정렬에는 이 column
유틸리티가 필요합니다.
예를 들어:
(
printf 'PID\tUSER\tAPPNAME\n'
printf '%s\t%s\t%s\n' "1" "john" "foo bar"
printf '%s\t%s\t%s\n' "12345678" "someone_with_a_long_name" "pop tart"
) | column -t -s $'\t'
결과 :
PID USER APPNAME
1 john foo bar
12345678 someone_with_a_long_name pop tart
답변2
또한 이 스크립트를 한 줄 명령으로 최적화할 수 있습니까?
-o
가능한 경우 명령 옵션을 사용하여 ps
관심 있는 필드만 출력한 다음 java
필요한 프로세스 및 특정 명령 매개 변수와 일치하도록 사후 처리를 고려할 것입니다.
ps -u $USER -o uname=,pid=,args= |
gawk -vOFS='\t' '/java/ {print $1,$2,substr($0,match($0,"-D(app[.]name)|(projectName)[^[:space:]]*"),RLENGTH)}'
아니면 이런 것일 수도 있습니다 perl
(면책조항: Perl에 대한 나의 지식은 대략적입니다.)
ps -u $USER -o uname=,pid=,args= |
perl -anle 'print join "\t", @F[0], @F[1], grep /-D(app[.]name)|(projectName)/,@F if /java/'
답변3
다음 출력 형식을 사용하는 또 다른 것이 있습니다 ps
.
#!/usr/bin/sh -f
printf '%-8.7s%-8s%s\n' $(
ps -o uname=UID,pid=PID,args=APPNAME |
sed -n '1p;s/\( [0-9]* \).*\(-Dapp.name=[^ ]*\).*/\1\2/p'
)
형식 문자열에 따라 3개의 인수가 모두 printf
인쇄됩니다.
- 오른쪽의 첫 번째 공백은 표준 탭 너비인 8자로 채워지고 최대 7자로 잘립니다.
- 오른쪽에서 두 번째 공백은 표준 탭 너비인 8자로 채워집니다.
- 세 번째 뒤에는
\n
eline이 옵니다.
명령 대체는아니요선두고의로. Bang-line에서 -f
다음 사항에 유의하십시오 sh
. 이는 쉘이 다음을 수행해야 함을 지정합니다.아니요glob - 쉘 특수 문자를 기반으로 파일 이름을 무작위로 생성할 위험이 없습니다. 명령 대체는 $IFS
기본적으로 공백, 탭, 줄 바꿈 등으로 분할됩니다.
명령 대체에서 ps
3개의 열을 인쇄합니다 - 제목사용자 ID,PID, 그리고애플리케이션 이름. ps
POSIX에 의해 지정됩니다아니요모든 필드의 공백을 인쇄하세요.제외하고필드 args=
. 따라서 처음 두 열은 $IFS
안전합니다. 하지만 문자열을 필드 -Dapp.name
밖으로 가져오려면 처리해야 합니다.args=
그러니 sed
필터링하세요. 두 개 이상의 공백과 문자열이 포함된 줄에-Dapp.name=다음과 같이 인쇄됩니다.
- 먼저 일련의 공백, 그 다음에는 0개 이상의 숫자, 그 다음에는 공백과 그 앞의 모든 숫자...
- 문자열을 포함하는 시퀀스의 마지막 발생-Dapp.name=다음에 공백이 발생하기 전의 모든 문자가 옵니다.
sed
교체는 열 헤더에 영향을 미치지 않습니다 1p
.-Dapp.name=끈. 다른 모든 줄은 출력에서 제거됩니다.
printf
sed
출력 분할을 적용한 후 $IFS
출력은 다음과 같을 것으로 예상할 수 있습니다.
UID PID APPNAME
sas 24431 -Dapp.name=myApp
sas 24431 -Dapp.name=myApp
sas 24431 -Dapp.name=myApp
sas 24431 -Dapp.name=myApp
sas 24431 -Dapp.name=myApp
그러나 내 생각에는 다음 sed
진술이 더 낫다.
sed -n '1p;s/\( [0-9]* \).*-Dapp.name=\([^ ]*\).*/\1\2/p'
기본적으로는 똑같습니다만 빼면-Dapp.name=부분 \2
이므로 다음과 같이 인쇄됩니다 ...
UID PID APPNAME
sas 24431 myApp
sas 24431 myApp
sas 24431 myApp
왜냐하면, 그렇기 때문에오직다음을 포함하는 줄을 인쇄하세요.-Dapp.name=어쨌든, 그것을 포함한 순서는 당연하게 여겨질 수 있는 혼란일 뿐입니다.