Linux에서 그래프 막대용 bash 스크립트를 만들었지만 스크립트가 너무 많은 프로세스를 생성하는 것 같습니다.
스크립트:
#!/usr/bin/bash
executable="/usr/local/bin/bar"
monitor=${1:-0}
monitor_geometry=($(hc monitor_rect) $monitor)
x=${monitor_geometry[0]}
y=${monitor_geometry[1]}
panel_width=${monitor_geometry[2]}
panel_height=20
line_height=2
font="-*-terminesspowerline-medium-*-*-*-12-*-*-*-*-*-*-*"
bgcolor="#ff073642"
selbgcolor="#fffdf6e3"
selfgcolor="#ffeee8d5"
normfgcolor="#ff586e75"
urgentcolor="#ffdc322f"
separator=" "
icon_signal_max="|||"
icon_signal_med="||-"
icon_signal_min="|--"
icon_battery_charging="-"
icon_battery_discharging="x"
icon_arrow_up=""
# function declarations
hc() {
"${herbstclient_command[@]:-herbstclient}" "$@";
}
unique() {
awk '$0 != l { print; l=$0; fflush(); }' "$@"
}
get_datetime() {
{
while true; do
date +"datetime %a %d-%m-%Y (%V) %H:%M"
sleep 60
done
} | unique
}
get_power_status() {
{
while true; do
acpi_status=$(acpi --battery | cut -d' ' -f3 | sed 's/,//')
charge_percentage=$(acpi --battery | cut -d' ' -f4 | sed 's/%.*//')
if [[ $acpi_status ]]; then
if [[ "$acpi_status" == "Charging" ]]; then
status="$charge_percentage%%"
elif [[ "$acpi_status" == "Discharging" ]]; then
status="$charge_percentage%%"
elif [[ "$acpi_status" == "Unknown" ]]; then
status=""
fi
fi
if [[ "$charge_percentage" -le "20" ]]; then
status="%{F$urgentcolor}$status{F-}"
fi
echo "power_status $status"
sleep 1
done
} | unique
}
get_network_status() {
{
while true; do
wlan_ssid=$(iwgetid -r)
if [ -n $wlan_ssid ]; then
signal_strength=$(cat /proc/net/wireless | awk 'NR==3 {print $3}' | sed 's/\.//')
if [ "$signal_strength" -ge 65 ]; then
status="$wlan_ssid $icon_signal_max"
elif [ "$signal_strength" -lt 65 -a "$signal_strength" -ge 40 ]; then
status="$wlan_ssid $icon_signal_med"
else
status="$wlan_ssid $icon_signal_min"
fi
else
status=""
fi
echo "network_status $status"
sleep 1
done
} | unique
}
get_cpu_status() {
{
while true; do
no_cores=$(nproc)
loadavg=$(cat /proc/loadavg | awk '{print $1}')
if [ $(echo "$loadavg >= $no_cores" | bc) -ne 0 ]; then
status="%{F${urgentcolor}}${loadavg}%{F${normfgcolor}}"
else
status="$loadavg"
fi
echo "cpu_status $status"
sleep 1
done
} | unique
}
# register panel
hc pad $monitor $panel_height
# event multiplexer
{
get_datetime &
children[1]=$!
get_power_status &
children[2]=$!
get_network_status &
children[3]=$!
get_cpu_status &
children[4]=$!
hc --idle
for pid in ${children[@]}; do
kill $pid
done
} 2> /dev/null | {
tags=$(hc tag_status $monitor)
unset tags[${#tags[@]}-1]
visible=true
while true ; do
echo -n "%{c}"
for i in ${tags[@]}; do
case ${i:0:1} in
'.') # empty tag
echo -n "%{-uF${normfgcolor}}"
;;
'#') # current tag
echo -n "%{+u U${selfgcolor} F${selfgcolor}}"
;;
'+') # active on other monitor
echo -n "%{-uF$selfgcolor}"
;;
':') # tag with window(s)
echo -n "%{-uF$selfgcolor}"
;;
'!') # urgent tag
echo -n "%{-uF${urgentcolor}}"
;;
*)
echo -n "%{-uF${normfgcolor}}"
;;
esac
echo -n " ${i:1} "
done
# align left
echo -n "%{lF$selfgcolor}"
echo -n " "
echo -n "$power_status"
echo -n "$network_status"
echo -n "$cpu_status"
# align right
echo -n "%{r}"
echo -n "$datetime"
echo -n " "
echo
# wait for next event
read line || break
cmd=( $line )
# find out event origin
case ${cmd[0]} in
tag*)
tags=$(hc tag_status $monitor)
unset tags[${#tags[@]}-1]
;;
datetime)
datetime="${cmd[@]:1}"
;;
power_status)
power_status="${cmd[@]:1}"
;;
network_status)
network_status="${cmd[@]:1}"
;;
cpu_status)
cpu_status="${cmd[@]:1}"
;;
reload)
exit
;;
quit_panel)
exit
;;
esac
done
} 2> /dev/null | $executable -g ${panel_width}x${panel_height}+${x}+${y} -f $font -u $line_height -B $bgcolor -F $selfgcolor
ps
산출:
jakob@jw-laptop:~% ps faux | grep panel.sh
jakob 26906 0.0 0.0 12908 2324 pts/1 S+ 02:34 0:00 \_ grep --color panel.sh
jakob 26616 0.0 0.0 15780 3220 ? S 02:34 0:00 /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26619 0.0 0.0 15780 1880 ? S 02:34 0:00 \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26622 0.0 0.0 15780 1624 ? S 02:34 0:00 | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26625 0.0 0.0 15780 1752 ? S 02:34 0:00 | | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26627 0.0 0.0 15780 1752 ? S 02:34 0:00 | | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26624 0.0 0.0 15780 1628 ? S 02:34 0:00 | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26633 0.0 0.0 15912 2496 ? S 02:34 0:00 | | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26634 0.0 0.0 15780 480 ? S 02:34 0:00 | | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26626 0.0 0.0 15780 1628 ? S 02:34 0:00 | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26631 0.0 0.0 15912 2560 ? S 02:34 0:00 | | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26632 0.0 0.0 15780 480 ? S 02:34 0:00 | | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26628 0.0 0.0 15780 1624 ? S 02:34 0:00 | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26637 0.0 0.0 15784 2556 ? S 02:34 0:00 | | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26638 0.0 0.0 15780 476 ? S 02:34 0:00 | | \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob 26620 0.0 0.0 15912 2556 ? S 02:34 0:00 \_ /usr/bin/bash /home/jakob/.config/herbstluftwm/panel.sh 0
jakob@jw-laptop:~%
데몬화할 수 있는 위치가 4개밖에 없는데 프로세스가 왜 그렇게 많습니까? 이 스크립트가 너무 많은 리소스를 사용하고 있다면 이를 수정하고 싶습니다.
답변1
이는 어디에서나 서브쉘을 시작하기 때문에 발생합니다 :-)
사용 중인 구문(사용 중인 위치 { some_stuff } 2>/dev/null | other_stuff
)은 중괄호 사이의 모든 코드 비트에 대한 하위 쉘을 생성합니다. 이는 다음 스크립트를 사용하여 상당히 쉽게 시연할 수 있습니다.
#!/bin/bash
{ sleep 1; } | { sleep 2; } | { sleep 3; } & ps axf
그러면 다음과 같은 출력이 생성됩니다.
phemmer 26014 19 0 0.0 0.0 S+ 00:00 \_ bash /tmp/test.sh
phemmer 26015 19 0 0.0 0.0 S+ 00:00 \_ bash /tmp/test.sh
phemmer 26018 19 0 0.0 0.0 S+ 00:00 | \_ sleep 1
phemmer 26016 19 0 0.0 0.0 S+ 00:00 \_ bash /tmp/test.sh
phemmer 26020 19 0 0.0 0.0 S+ 00:00 | \_ sleep 2
phemmer 26017 19 0 0.0 0.0 S+ 00:00 \_ bash /tmp/test.sh
phemmer 26021 19 0 0.0 0.0 S+ 00:00 | \_ sleep 3
phemmer 26019 19 0 0.0 0.0 R+ 00:00 \_ ps axf
그 이유는 파이프라인의 모든 명령이 동시에 실행되어야 하기 때문입니다. 따라서 껍질을 포크해야 합니다.
Linux는 포크할 때 쓰기 시 복사 메모리 할당을 사용하므로 이는 큰 리소스 낭비가 아닙니다. 이는 프로세스가 포크될 때 메모리 사용량이 두 배가 되지 않음을 의미합니다. 두 프로세스 중 하나가 해당 메모리를 변경할 때까지 두 프로세스 모두 동일한 메모리를 사용합니다. 변경이 발생하면 특정 메모리 페이지가 복사됩니다.
유일한 해결책은 동일한 파이프라인에서 스크립트의 여러 부분을 실행하지 않는 것입니다. 이를 달성하는 방법은 전적으로 귀하에게 달려 있습니다. 한 가지 옵션은 서브셸에서 마지막 명령을 사용하는
것입니다 . exec
이러한 방식으로 실행 중인 명령은 셸의 PID를 인수합니다.