-
Notifications
You must be signed in to change notification settings - Fork 0
/
optimize_php.sh
324 lines (266 loc) · 10.9 KB
/
optimize_php.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#!/bin/bash
# Improved PHP-FPM Optimization Script with Error Handling and Logging
# Exit immediately if a command exits with a non-zero status
set -e
# Function to display usage information
usage() {
echo "Usage: sudo $0 [--debug]"
echo "This script detects installed PHP versions, shows current and proposed settings, and allows you to choose which to optimize."
echo "Options:"
echo " --debug Enable debug mode for verbose logging"
}
# Check if script is run as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
usage
exit 1
fi
# Initialize debug mode flag
DEBUG=false
# Parse command line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
--debug) DEBUG=true ;;
*) echo "Unknown parameter: $1"; usage; exit 1 ;;
esac
shift
done
# Function for debug logging
debug_log() {
if $DEBUG; then
echo "[DEBUG] $1" >&2
fi
}
# Function to detect installed PHP versions
detect_php_versions() {
debug_log "Detecting installed PHP versions"
ls /etc/php/ 2>/dev/null | grep -E '^[0-9]+\.[0-9]+$' || echo "No PHP versions detected"
}
# Detect installed PHP versions
mapfile -t PHP_VERSIONS < <(detect_php_versions)
if [ ${#PHP_VERSIONS[@]} -eq 0 ]; then
echo "No PHP versions detected. Please install PHP-FPM first."
exit 1
fi
debug_log "Detected PHP versions: ${PHP_VERSIONS[*]}"
# Function to create a backup with timestamp
create_backup() {
local file=$1
local backup_dir="/root/php_backups"
mkdir -p "$backup_dir"
local backup_file="$backup_dir/$(basename "$file").$(date +%Y%m%d%H%M%S).bak"
cp "$file" "$backup_file"
echo "Backup created: $backup_file"
debug_log "Created backup: $backup_file"
}
# Function to get current value of a parameter
get_current_value() {
local file=$1
local param=$2
if [ ! -f "$file" ]; then
echo "Configuration file not found: $file" >&2
return 1
fi
grep -E "^$param\s*=" "$file" | cut -d'=' -f2- | tr -d '[:space:]' || echo "Not set"
}
# Function to update configuration file
update_config() {
local file=$1
local param=$2
local value=$3
local current_value
if [ ! -f "$file" ]; then
echo "Configuration file not found: $file" >&2
return 1
fi
current_value=$(get_current_value "$file" "$param")
if [ "$current_value" != "$value" ]; then
sed -i "s/^$param\s*=.*$/$param = $value/" "$file"
echo "Updated $param: $current_value -> $value"
debug_log "Updated $param in $file: $current_value -> $value"
else
echo "$param is already set to $value"
debug_log "$param is already set to $value in $file"
fi
}
# Function to calculate system resources and PHP-FPM settings for a specific version
calculate_php_fpm_settings() {
local php_version=$1
local total_ram=$(free -m | awk '/Mem/{print $2}')
local cpu_cores=$(nproc)
debug_log "Calculating settings for PHP $php_version"
debug_log "Total RAM: $total_ram MB, CPU cores: $cpu_cores"
# Calculate average PHP-FPM process size for this specific version
local avg_process_size=$(ps -C php-fpm$php_version --no-headers -o rss 2>/dev/null | awk '{ sum += $1; count++ } END { if (count > 0) print int(sum / count / 1024); else print "0" }')
if [ "$avg_process_size" == "0" ]; then
echo "Warning: No PHP-FPM $php_version processes are currently running. Using default values for calculations." >&2
avg_process_size=50 # Default value in MB if no processes are running
fi
debug_log "Average PHP-FPM $php_version process size: $avg_process_size MB"
# Calculate recommended settings
local max_children=$((total_ram / avg_process_size))
local start_servers=$((cpu_cores * 2))
local min_spare_servers=$cpu_cores
local max_spare_servers=$((cpu_cores * 3))
local recommended_memory_limit="256M"
debug_log "Calculated settings: max_children=$max_children, start_servers=$start_servers, min_spare_servers=$min_spare_servers, max_spare_servers=$max_spare_servers, memory_limit=$recommended_memory_limit"
echo "$max_children $start_servers $min_spare_servers $max_spare_servers $recommended_memory_limit $avg_process_size"
}
# Function to get and display PHP-FPM settings
get_php_fpm_settings() {
local php_version=$1
local pool_conf="/etc/php/$php_version/fpm/pool.d/www.conf"
local php_ini="/etc/php/$php_version/fpm/php.ini"
debug_log "Getting settings for PHP $php_version"
if [ ! -f "$pool_conf" ] || [ ! -f "$php_ini" ]; then
debug_log "Configuration files for PHP $php_version not found. Skipping."
return 1
fi
# Get recommended settings
read -r rec_max_children rec_start_servers rec_min_spare_servers rec_max_spare_servers rec_memory_limit avg_process_size <<< $(calculate_php_fpm_settings $php_version)
echo "PHP $php_version settings:"
echo "Average PHP-FPM process size: $avg_process_size MB"
# Function for formatted output of settings
print_setting() {
local param=$1
local current=$2
local recommended=$3
printf "%-25s = %-10s | Recommended = %-10s\n" "$param" "$current" "$recommended"
}
print_setting "pm.max_children" "$(get_current_value "$pool_conf" "pm.max_children")" "$rec_max_children"
print_setting "pm.start_servers" "$(get_current_value "$pool_conf" "pm.start_servers")" "$rec_start_servers"
print_setting "pm.min_spare_servers" "$(get_current_value "$pool_conf" "pm.min_spare_servers")" "$rec_min_spare_servers"
print_setting "pm.max_spare_servers" "$(get_current_value "$pool_conf" "pm.max_spare_servers")" "$rec_max_spare_servers"
print_setting "memory_limit" "$(get_current_value "$php_ini" "memory_limit")" "$rec_memory_limit"
echo
}
# Function to optimize a single PHP version
optimize_php_version() {
local php_version=$1
echo "Optimizing PHP $php_version"
debug_log "Starting optimization for PHP $php_version"
# Define file paths
local pool_conf="/etc/php/$php_version/fpm/pool.d/www.conf"
local php_ini="/etc/php/$php_version/fpm/php.ini"
if [ ! -f "$pool_conf" ] || [ ! -f "$php_ini" ]; then
debug_log "Configuration files for PHP $php_version not found. Skipping optimization for this version."
return 1
fi
# Create backups
create_backup "$pool_conf"
create_backup "$php_ini"
# Get recommended settings
read -r max_children start_servers min_spare_servers max_spare_servers recommended_memory_limit avg_process_size <<< $(calculate_php_fpm_settings $php_version)
# Update pool configuration
update_config "$pool_conf" "pm.max_children" "$max_children"
update_config "$pool_conf" "pm.start_servers" "$start_servers"
update_config "$pool_conf" "pm.min_spare_servers" "$min_spare_servers"
update_config "$pool_conf" "pm.max_spare_servers" "$max_spare_servers"
# Update PHP memory limit
update_config "$php_ini" "memory_limit" "$recommended_memory_limit"
# Test configuration files
if ! php-fpm$php_version -t; then
echo "Error: Configuration files for PHP $php_version are invalid. Rolling back changes." >&2
rollback_changes "$pool_conf" "$php_ini"
return 1
fi
# Restart PHP-FPM
if systemctl is-active --quiet "php$php_version-fpm"; then
if systemctl restart "php$php_version-fpm"; then
echo "PHP-FPM $php_version restarted successfully"
debug_log "PHP-FPM $php_version restarted successfully"
else
echo "Failed to restart PHP-FPM $php_version. Rolling back changes." >&2
rollback_changes "$pool_conf" "$php_ini"
return 1
fi
else
echo "PHP-FPM $php_version is not running. Skipping restart."
debug_log "PHP-FPM $php_version is not running. Skipping restart."
fi
echo "Optimization for PHP $php_version completed"
debug_log "Optimization for PHP $php_version completed"
echo
}
# Function to roll back changes
rollback_changes() {
local pool_conf=$1
local php_ini=$2
local backup_dir="/root/php_backups"
echo "Rolling back changes for PHP $php_version"
debug_log "Rolling back changes for PHP $php_version"
# Restore backup files
cp "$backup_dir/$(basename "$pool_conf")."*".bak" "$pool_conf"
cp "$backup_dir/$(basename "$php_ini")."*".bak" "$php_ini"
echo "Changes rolled back successfully"
debug_log "Changes rolled back successfully"
}
# Function to validate PHP version selection
validate_php_version_selection() {
local choice=$1
local selected_versions=()
if [[ $choice == "0" ]]; then
for version in "${PHP_VERSIONS[@]}"; do
local pool_conf="/etc/php/$version/fpm/pool.d/www.conf"
local php_ini="/etc/php/$version/fpm/php.ini"
if [ -f "$pool_conf" ] && [ -f "$php_ini" ]; then
selected_versions+=("$version")
fi
done
else
IFS=',' read -ra selected_indices <<< "$choice"
for index in "${selected_indices[@]}"; do
if [[ $index =~ ^[0-9]+$ ]] && [[ $index -le ${#PHP_VERSIONS[@]} && $index -gt 0 ]]; then
local version=${PHP_VERSIONS[$((index-1))]}
local pool_conf="/etc/php/$version/fpm/pool.d/www.conf"
local php_ini="/etc/php/$version/fpm/php.ini"
if [ -f "$pool_conf" ] && [ -f "$php_ini" ]; then
selected_versions+=("$version")
fi
else
echo "Invalid PHP version selection: $index" >&2
fi
done
fi
echo "${selected_versions[@]}"
}
# Main script logic
echo "Detected PHP versions: ${PHP_VERSIONS[*]}"
echo
echo "System information:"
echo "Total RAM: $(free -m | awk '/Mem/{print $2}') MB"
echo "CPU cores: $(nproc)"
echo
# Display current settings and recommended changes for available versions
available_versions=()
for version in "${PHP_VERSIONS[@]}"; do
if get_php_fpm_settings "$version"; then
available_versions+=("$version")
fi
done
if [ ${#available_versions[@]} -eq 0 ]; then
echo "No PHP versions with valid configurations found. Exiting."
exit 1
fi
echo "Select PHP versions to optimize:"
echo "0) All available versions"
for i in "${!available_versions[@]}"; do
echo "$((i+1))) ${available_versions[i]}"
done
read -p "Enter your choice (comma-separated numbers, e.g., 1,2 or 0 for all): " choice
selected_versions=($(validate_php_version_selection "$choice"))
if [ ${#selected_versions[@]} -eq 0 ]; then
echo "No valid PHP versions selected. Exiting."
exit 1
fi
echo "You've selected to optimize the following PHP versions: ${selected_versions[*]}"
read -p "Do you want to proceed with the optimization? (y/n) " confirm
if [[ $confirm != [yY] ]]; then
echo "Optimization cancelled."
exit 0
fi
for version in "${selected_versions[@]}"; do
optimize_php_version "$version"
done
echo "PHP-FPM optimization process completed for selected versions"
debug_log "Script execution completed"