Я ищу способ перечислить все сессии, что-то как команда, кто, который также перечислил бы тип оболочки, используемой списком пользователей.
В зависимости от того, что Вы хотите, можно использовать who
кузен w
:
$ w
17:40:49 up 11 days, 22:38, 4 users, load average: 0.14, 0.13, 0.10
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
muru tty7 :0 12Jan17 11days 2:24m 0.37s /sbin/upstart --user
muru pts/24 127.0.0.1:S.0 17:36 0.00s 0.41s 0.00s w
muru pts/26 127.0.0.1:S.2 17:38 2:33 0.19s 0.19s -/bin/zsh
Это выполняет активную команду на терминале входа в систему. Можно использовать терминальный идентификатор для наблюдения, какую оболочку я запустил первоначально:
$ w -h | awk '{print $2}' | xargs -L1 pgrep -oat
1969 /usr/lib/xorg/Xorg -core :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch
12703 -/bin/zsh
13398 -/bin/zsh
pgrep
может:
-t
) -o
) -a
) Информация о Shell с дочерними процессами
ps -efH | egrep 'pts/|tty'
sup 14536 2065 0 17:05 pts/19 00:00:00 bash
sup 14572 14536 0 17:05 pts/19 00:00:00 dash
sup 14575 14572 0 17:05 pts/19 00:00:00 bash
sup 14611 14575 0 17:05 pts/19 00:00:00 dash
sup 14673 1956 0 17:06 pts/6 00:00:00 /bin/bash
sup 14717 14673 0 17:06 pts/6 00:00:00 bash
sup 15650 14717 0 17:16 pts/6 00:00:00 ps -efH
Так как все установленные оболочки в Вашей системе перечислены в /etc/shells
, можно запустить оттуда и использование ps
перечислять, которые работают и связанная информация.
Так, во-первых, получите список оболочек:
$ grep -oP '^/.*/\K.*' /etc/shells | sort -u
bash
csh
dash
fish
ksh
mksh
sh
tcsh
zsh
-o
означает "печать только часть соответствия строки" и -P
включает PCRE, Perl Совместимые Регулярные выражения, которые позволяют нам использовать необычные вещи как \K
, что означает, "игнорируют все подобранное до этой точки". Так, ^/.*/\K.*
средства соответствуют строкам, запускающимся с a /
(^/
), затем как можно больше символов до a /
(.*/
), затем забудьте о том, что было подобрано до сих пор (\K
) и соответствуйте всему остальному до конца строки. Это эффективно возвратит последнюю часть каждой строки, подлинное имя оболочки (например. bash
для /bin/bash
).
sort -u
просто гарантирует, что никакие оболочки не печатаются дважды (иногда, у Вас может быть та же оболочка в обоих /bin
и /usr/bin
).
Но, мы хотим использовать этот список для поиска вывода ps
, таким образом, нам нужен он в формате это grep
может понять:
$ grep -oP '^/.*/\K.*' /etc/shells | sort -u | perl -pe '!eof && s/\n/\|/'
bash|csh|dash|fish|ksh|mksh|sh|tcsh|zsh
Это perl
управляйте просто заменяет символы новой строки (\n
) с |
, таким образом, это может питаться непосредственно к grep
.
Мы теперь используем pgrep
перечислять все процессы соответствия:
$ pgrep -x "$(grep -oP '^/.*/\K.*' /etc/shells | sort -u |
perl -pe '!eof && s/\n/\|/')"
1235
5399
14031
14116
14200
14304
14337
14392
15257
15368
15551
15601
15704
15877
17033
28177
29138
30797
32404
32656
-x
необходим так, чтобы только обработал то соответствие точно (так нет foosh
для sh
).
Теперь, когда у нас есть список целевого PIDs, мы можем передать их ps
и используйте его для печати релевантной информации:
$ pgrep -x "$(grep -oP '^/.*/\K.*' /etc/shells | sort -u |
perl -pe '!eof && s/\n/\|/')" |
while read pid; do ps -p $pid -o pid=,cmd=,euser=,tty=; done
1235 /bin/bash terdon pts/1
5399 /bin/bash terdon pts/4
12341 /bin/bash terdon pts/2
14031 /bin/bash terdon pts/8
14116 /bin/bash terdon pts/9
14200 /bin/bash terdon pts/10
14304 /bin/bash terdon pts/11
14337 /bin/bash terdon pts/12
14392 /bin/bash terdon pts/13
15257 dash terdon pts/13
15368 zsh terdon pts/12
15551 mksh terdon pts/11
15601 -sh terdon pts/10
15704 -csh terdon pts/9
15877 sh terdon pts/8
17033 /bin/bash terdon pts/2
28177 /bin/bash terdon pts/3
29138 fish terdon pts/3
30797 /bin/bash terdon pts/5
32404 /bin/bash terdon pts/6
32656 /bin/bash terdon pts/7
Это читает каждый PID, произведенный предыдущими шагами и выполнениями ps
для него (-p $pid
), использование -o
отметьте для управления выводом для печати PID, команда использовала, пользователь, который запустил его и оконечное устройство, к которому это присоединено.
Вот сценарий, который перечисляет PID оболочки, ее двоичного файла, терминала, к которому stdin оболочки присоединяется, и имя пользователя владельца процесса. Сценарий делает широкое применение /proc
файловая система для лучшей точности.
То, что Вы видите в снимке экрана ниже, является демонстрационным выполнением того сценария. Я имею два, взламывает с эмулятором терминала Терминатора. Числом в квадратных скобках каждой подсказки является PID той оболочки. Главное разделение подтверждает, что я имею два mksh
экземпляры открываются в виртуальных псевдотерминалах, который является терминалами GUI и одним экземпляром удара. Другой mksh
экземпляр может быть найден в tty1
. То, что также интересно, существует два dash
экземпляры, присоединенные к /dev/null
. После исследования процессов, которым они принадлежат, оказывается, что они принадлежат Одной единице appindicator и сервис духа времени. Таким образом в этом сценарии легче видеть, какие оболочки на самом деле используются реальными пользователями, и который системными процессами.
Источник сценария ниже и также доступен на GitHub
#!/usr/bin/env bash
is_self(){
if [ "$link" == "/bin/bash" ] && grep -q $0 /proc/$proc_pid/cmdline
then
return 0
else
return 1
fi
}
print_proc_info(){
terminal=$( readlink -e "/proc/$proc_pid/fd/0" )
[ -z "$terminal" ] && terminal=$'\t'
printf "%s\t%s\t%s\t" "$proc_pid" "$1" "$terminal"
stat --printf="%U\n" /proc/"$proc_pid"/mountstats
}
find_process(){
local function_pid=$$
local search_base=$(basename "$1")
find /proc -maxdepth 1 -type d -path "*/[1-9]*" | while read -r proc_dir;
do
local proc_pid=$(basename "$proc_dir")
local link=$(readlink -e "$proc_dir"/exe)
local name=$( awk 'NR==1{print $2}' "$proc_dir"/status 2>/dev/null )
if is_self ; then continue ; fi
if [ "$link" == "$1" ] ||
[ -z "$link" ] && [ "$name" = "$search_base" ]
then
print_proc_info $1
# make additional check if readlink wasn't allowed to
# get where /proc/[pid]/exe is symlinked
fi
done
}
main(){
while read -r shell
do
find_process "$shell"
done < /etc/shells
echo "Done, press [ENTER] to continue"
read
}
main