| #!/bin/sh |
| |
|
|
| set -eu |
|
|
| LC_ALL=C |
| ME=$( basename "$0" ) |
| PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
|
|
| [ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 |
|
|
| touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } |
|
|
| ceildiv() { |
| num=$1 |
| div=$2 |
| echo $(( (num + div - 1) / div )) |
| } |
|
|
| get_cpuset() { |
| cpusetroot=$1 |
| cpusetfile=$2 |
| ncpu=0 |
| [ -f "$cpusetroot/$cpusetfile" ] || return 1 |
| for token in $( tr ',' ' ' < "$cpusetroot/$cpusetfile" ); do |
| case "$token" in |
| *-*) |
| count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) |
| ncpu=$(( ncpu+count )) |
| ;; |
| *) |
| ncpu=$(( ncpu+1 )) |
| ;; |
| esac |
| done |
| echo "$ncpu" |
| } |
|
|
| get_quota() { |
| cpuroot=$1 |
| ncpu=0 |
| [ -f "$cpuroot/cpu.cfs_quota_us" ] || return 1 |
| [ -f "$cpuroot/cpu.cfs_period_us" ] || return 1 |
| cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) |
| cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) |
| [ "$cfs_quota" = "-1" ] && return 1 |
| [ "$cfs_period" = "0" ] && return 1 |
| ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) |
| [ "$ncpu" -gt 0 ] || return 1 |
| echo "$ncpu" |
| } |
|
|
| get_quota_v2() { |
| cpuroot=$1 |
| ncpu=0 |
| [ -f "$cpuroot/cpu.max" ] || return 1 |
| cfs_quota=$( cut -d' ' -f 1 < "$cpuroot/cpu.max" ) |
| cfs_period=$( cut -d' ' -f 2 < "$cpuroot/cpu.max" ) |
| [ "$cfs_quota" = "max" ] && return 1 |
| [ "$cfs_period" = "0" ] && return 1 |
| ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) |
| [ "$ncpu" -gt 0 ] || return 1 |
| echo "$ncpu" |
| } |
|
|
| get_cgroup_v1_path() { |
| needle=$1 |
| found= |
| foundroot= |
| mountpoint= |
|
|
| [ -r "/proc/self/mountinfo" ] || return 1 |
| [ -r "/proc/self/cgroup" ] || return 1 |
|
|
| while IFS= read -r line; do |
| case "$needle" in |
| "cpuset") |
| case "$line" in |
| *cpuset*) |
| found=$( echo "$line" | cut -d ' ' -f 4,5 ) |
| break |
| ;; |
| esac |
| ;; |
| "cpu") |
| case "$line" in |
| *cpuset*) |
| ;; |
| *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) |
| found=$( echo "$line" | cut -d ' ' -f 4,5 ) |
| break |
| ;; |
| esac |
| esac |
| done << __EOF__ |
| $( grep -F -- '- cgroup ' /proc/self/mountinfo ) |
| __EOF__ |
|
|
| while IFS= read -r line; do |
| controller=$( echo "$line" | cut -d: -f 2 ) |
| case "$needle" in |
| "cpuset") |
| case "$controller" in |
| cpuset) |
| mountpoint=$( echo "$line" | cut -d: -f 3 ) |
| break |
| ;; |
| esac |
| ;; |
| "cpu") |
| case "$controller" in |
| cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) |
| mountpoint=$( echo "$line" | cut -d: -f 3 ) |
| break |
| ;; |
| esac |
| ;; |
| esac |
| done << __EOF__ |
| $( grep -F -- 'cpu' /proc/self/cgroup ) |
| __EOF__ |
|
|
| case "${found%% *}" in |
| "/") |
| foundroot="${found##* }$mountpoint" |
| ;; |
| "$mountpoint") |
| foundroot="${found##* }" |
| ;; |
| esac |
| echo "$foundroot" |
| } |
|
|
| get_cgroup_v2_path() { |
| found= |
| foundroot= |
| mountpoint= |
|
|
| [ -r "/proc/self/mountinfo" ] || return 1 |
| [ -r "/proc/self/cgroup" ] || return 1 |
|
|
| while IFS= read -r line; do |
| found=$( echo "$line" | cut -d ' ' -f 4,5 ) |
| done << __EOF__ |
| $( grep -F -- '- cgroup2 ' /proc/self/mountinfo ) |
| __EOF__ |
|
|
| while IFS= read -r line; do |
| mountpoint=$( echo "$line" | cut -d: -f 3 ) |
| done << __EOF__ |
| $( grep -F -- '0::' /proc/self/cgroup ) |
| __EOF__ |
|
|
| case "${found%% *}" in |
| "") |
| return 1 |
| ;; |
| "/") |
| foundroot="${found##* }$mountpoint" |
| ;; |
| "$mountpoint") |
| foundroot="${found##* }" |
| ;; |
| esac |
| echo "$foundroot" |
| } |
|
|
| ncpu_online=$( getconf _NPROCESSORS_ONLN ) |
| ncpu_cpuset= |
| ncpu_quota= |
| ncpu_cpuset_v2= |
| ncpu_quota_v2= |
|
|
| cpuset=$( get_cgroup_v1_path "cpuset" ) && ncpu_cpuset=$( get_cpuset "$cpuset" "cpuset.effective_cpus" ) || ncpu_cpuset=$ncpu_online |
| cpu=$( get_cgroup_v1_path "cpu" ) && ncpu_quota=$( get_quota "$cpu" ) || ncpu_quota=$ncpu_online |
| cgroup_v2=$( get_cgroup_v2_path ) && ncpu_cpuset_v2=$( get_cpuset "$cgroup_v2" "cpuset.cpus.effective" ) || ncpu_cpuset_v2=$ncpu_online |
| cgroup_v2=$( get_cgroup_v2_path ) && ncpu_quota_v2=$( get_quota_v2 "$cgroup_v2" ) || ncpu_quota_v2=$ncpu_online |
|
|
| ncpu=$( printf "%s\n%s\n%s\n%s\n%s\n" \ |
| "$ncpu_online" \ |
| "$ncpu_cpuset" \ |
| "$ncpu_quota" \ |
| "$ncpu_cpuset_v2" \ |
| "$ncpu_quota_v2" \ |
| | sort -n \ |
| | head -n 1 ) |
|
|
| sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf |