Jawaban:
Apakah ada cara untuk menghasilkan
lstartdalam format ISO sepertiYYYY-MM-DD HH:MM:SS?
Dengan awk+ datekerja sama:
ps -eo lstart,pid,cmd --sort=start_time | awk '{
cmd="date -d\""$1 FS $2 FS $3 FS $4 FS $5"\" +\047%Y-%m-%d %H:%M:%S\047";
cmd | getline d; close(cmd); $1=$2=$3=$4=$5=""; printf "%s\n",d$0 }'
Pendekatan alternatif menggunakan kata kunci ps etimes (waktu yang berlalu sejak proses dimulai, dalam detik):
ps -eo etimes,pid,cmd --sort=etimes | awk '{
cmd="date -d -"$1"seconds +\047%Y-%m-%d %H:%M:%S\047";
cmd | getline d; close(cmd); $1=""; printf "%s\n",d$0 }'
date -d -"$1"seconds- perbedaan antara cap waktu saat ini dan elapsedwaktu, akan memberikan nilai cap waktu prosesetimesalih-alih lstartAnda mendapatkan waktu yang berlalu dalam detik yang sedikit lebih mudah untuk dilewatkan date -d -999seconds.
Anda dapat mengurutkan dengan:
ps -eo lstart,pid,cmd --sort=start_time
Perhatikan bahwa lstartitu bukan salah satu dari pskolom Unix standar .
Tidak semua sistem memiliki satu, dan output bervariasi antara implementasi dan berpotensi antar lokal.
Misalnya, di FreeBSD atau dengan psdari procps-ng(seperti yang biasanya ditemukan pada sistem berbasis Linux yang tidak tertanam) dan Clokal, Anda akan mendapatkan:
Wed Nov 1 12:36:15 2017
Di MacOS:
Wed 1 Nov 12:36:15 2017
Juga, karena tidak memberi Anda offset GMT, outputnya ambigu dalam zona waktu yang menerapkan DST (di mana ada satu jam selama tahun di mana tanggal yang sama terjadi dua kali) dan tidak selalu menyortir secara kronologis.
Di sini, Anda bisa memaksa kali menjadi UTC dan menggunakan perl's Date::Manipmodul untuk mengurai tanggal dengan cara yang mengerti format alam yang berbeda:
(export TZ=UTC0 LC_ALL=C
ps -A -o lstart= -o pid= -o args= |
perl -MDate::Manip -lpe '
s/^(\s*\S+){5}/UnixDate(ParseDate($&), "%Y-%m-%dT%T+00:00")/e' |
sort
)
Atau ksh93yang juga mengenali format tanggal tersebut:
(export TZ=UTC0 LC_ALL=C
unset -v IFS
ps -A -o lstart= -o pid= -o args= |
while read -r a b c d e rest; do
printf '%(%FT%T+00:00)T %s\n' "$a $b $c $d $e" "$rest"
done
)
(hati-hati, strip kosong kosong dari setiap baris)
Atau dengan zshdan GNU date:
(export LC_ALL=C TZ=UTC0
(){
paste -d '\0' <(cut -c1-24 < $1 | date -f- --iso-8601=s) \
<(cut -c25- < $1) | sort
} =(ps -A -o lstart= -o pid= -o args=)
)
Atau dengan bash(atau zsh) hanya di Linux dan dengan GNU date:
(export LC_ALL=C TZ=UTC0
{
paste -d '\0' <(cut -c1-24 | date -f- --iso-8601=s) \
<(cut -c25- < /dev/stdin) | sort
} <<< "$(ps -A -o lstart= -o pid= -o args=)"
)
Berhati-hatilah juga bahwa waktu mulai proses tidak harus sama dengan waktu terakhir proses mengeksekusi suatu perintah karena proses secara umum dapat menjalankan lebih dari satu perintah dalam masa hidup mereka (yang biasanya bukan yang tidak pernah menjalankan perintah) . Dengan kata lain, itu tidak selalu sesuai dengan waktu perintah ( argsbidang, standar yang setara dengan cmd) dimulai.
$ sh -c 'sleep 4; exec sleep 123' & sleep 234 & sleep 5
[1] 9380
[2] 9381
$ (export TZ=UTC0 LC_ALL=C; ps -o lstart,pid,args | perl -MDate::Manip -lpe 's/^(\s*\S+){5}/UnixDate(ParseDate($&), "%Y-%m-%dT%T+00:00")/e')
2017-10-30T17:21:06+00:00 3071 zsh
2017-11-01T15:47:48+00:00 9380 sleep 123
2017-11-01T15:47:48+00:00 9381 sleep 234
Lihat bagaimana sleep 123ini dilihat sebagai telah dimulai pada saat yang sama sleep 234meskipun itu dimulai 4 detik kemudian. Itu karena proses 9388 itu awalnya berjalan sh(dan menunggu 4 detik sleep 4) sebelum dieksekusi sleep 123(dan sebelum itu, itu menjalankan zshkode seperti yang bercabang oleh shell interaktif saya, jadi pada titik waktu yang berbeda, untuk proses itu, Anda harus memiliki terlihat di psoutput:, zshlalu sh, lalu sleep).
Berikut ini adalah implementasi dengan kinerja yang lebih tinggi (tidak perlu menjalankan proses baru per baris):
ps -eo etimes,pid,args --sort=etimes | awk 'BEGIN{now=systime()} {$1=strftime("%Y-%m-%d %H:%M:%S", now-$1); print $0}'
dan ini memungkinkan cukup mudah untuk mengubah pemesanan kolom juga. Misalnya pidpertama dan waktu mulai sebagai kolom kedua:
ps -eo pid,etimes,args --sort=etimes | awk 'BEGIN{now=systime()} {$2=strftime("%Y-%m-%d %H:%M:%S", now-$2); print $0}'
lstartmemiliki format yang aneh. Itu dekat dengan RFC 2822 tetapi dengan tahun pada akhirnya.