--- tags: - maturity/🌱 date: 2023-11-20 zero-link: - "[[../../meta/zero/00 Π‘Π½ΠΈΠΏΠ΅Ρ‚Ρ‹ Π½Π° bash|00 Π‘Π½ΠΈΠΏΠ΅Ρ‚Ρ‹ Π½Π° bash]]" parents: - "[[../fundamental/Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ…|Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ…]]" linked: --- Π”Π°Π½Π½Ρ‹ΠΉ скрипт ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для автоматичСского сТатия ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ² PNG ΠΈ JPEG Π² Π·Π°Π΄Π°Π½Π½ΠΎΠΉ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ. Он ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ соврСмСнныС ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ сТатия, обСспСчивая ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΈΠ΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Ρ„Π°ΠΉΠ»ΠΎΠ² Π±Π΅Π· Π·Π°ΠΌΠ΅Ρ‚Π½ΠΎΠΉ ΠΏΠΎΡ‚Π΅Ρ€ΠΈ качСства. Π­Ρ‚ΠΎ особСнно ΠΏΠΎΠ»Π΅Π·Π½ΠΎ для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ Π²Π΅Π±-сайтов, ускорСния Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ страниц ΠΈ экономии дискового пространства. > [!NOTE] > Π›ΡƒΡ‡ΡˆΠ΅Π΅, Π½Π° ΠΌΠΎΠΉ взгляд, ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ для сТатия jpg это JPEGmini Pro. Π˜ΠΌΠ΅Π΅Ρ‚ Π²Π΅Ρ€ΡΠΈΡŽ cli для сСрвСров. Но ΠΊ соТалСнию ΠΎΠ½ΠΎ ΠΏΠ»Π°Ρ‚Π½ΠΎΠ΅. Π•Π³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ сТатия 2.2 ΠΌΠ± β€”> 959 ΠΊΠ±. ## Установка Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Ρ… ΡƒΡ‚ΠΈΠ»ΠΈΡ‚ ΠŸΠ΅Ρ€Π΅Π΄ запуском скрипта Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹: - **pngquant** β€” инструмСнт для сТатия PNG-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ. - **zopflipng** β€” ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Π° для Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ PNG-Ρ„Π°ΠΉΠ»ΠΎΠ² ΠΎΡ‚ Google. - **mozjpeg** β€” ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ JPEG-ΠΊΠΎΠ΄Π΅ΠΊ ΠΎΡ‚ Mozilla для сТатия JPEG-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ. ```shell # Для Debian/Ubuntu sudo apt-get install pngquant sudo apt-get install zopfli sudo apt-get install mozjpeg # Для macOS с использованиСм Homebrew brew install pngquant brew install zopfli brew install mozjpeg ``` - [[../linux/rhel/Установка ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ mozjpeg Π½Π° RHEL|Установка ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ mozjpeg Π½Π° RHEL]] ```shell title="zip_image.sh" #!/bin/bash # Настройки IMAGE_DIR="./images" COMP_DIR="$IMAGE_DIR/comp" # АвтоматичСскоС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ количСства ядСр процСссора THREADS=$(getconf _NPROCESSORS_ONLN) echo "Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ $THREADS ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ." # Π€Π°ΠΉΠ»Ρ‹ логирования LOG_FILE="./zip_image_compression.log" ERROR_LOG_FILE="./zip_image_error.log" # ЭкспортируСм Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ для использования Π² subshell export IMAGE_DIR COMP_DIR LOG_FILE ERROR_LOG_FILE # Ѐункция для опрСдСлСния Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Ρ„Π°ΠΉΠ»Π° get_file_size() { local file="$1" if [[ "$OSTYPE" == "linux-gnu"* ]]; then stat -c%s "$file" elif [[ "$OSTYPE" == "darwin"* ]]; then stat -f%z "$file" else # ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ GNU stat, Ссли установлСн if command -v gstat &> /dev/null; then gstat -c%s "$file" else # Π’ качСствС Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ wc -c wc -c < "$file" | tr -d ' ' fi fi} export -f get_file_size # Ѐункция для логирования успСха log_success() { local message="$1" echo "$message" echo "$(date '+%Y-%m-%d %H:%M:%S') $message" >> "$LOG_FILE" } # Ѐункция для логирования ошибок log_error() { local message="$1" echo "$message" >&2 echo "$(date '+%Y-%m-%d %H:%M:%S') $message" >> "$ERROR_LOG_FILE" } # ЭкспортируСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ логирования export -f log_success export -f log_error # Ѐункция для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ PNG Ρ„Π°ΠΉΠ»ΠΎΠ² process_png() { local input_file="$1" local relative_path="${input_file#$IMAGE_DIR/}" local output_file="$COMP_DIR/$relative_path" local output_dir output_dir="$(dirname "$output_file")" mkdir -p "$output_dir" # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ„Π°ΠΉΠ»Π° ошибки local error_file="${output_file}.error" if [ -f "$error_file" ]; then # Π€Π°ΠΉΠ» ошибки сущСствуСт, пропускаСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ return fi # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ…Π΅ΡˆΠ° Ρ„Π°ΠΉΠ»Π° local hash_file="${output_file}.md5" local current_hash current_hash="$(md5sum "$input_file" | awk '{print $1}')" if [ -f "$hash_file" ]; then local previous_hash previous_hash="$(cat "$hash_file")" if [ "$current_hash" == "$previous_hash" ]; then # Π€Π°ΠΉΠ» Π½Π΅ измСнился, Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅ΠΌ return fi fi # Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ local temp_output_file="${output_file}.tmp" cp "$input_file" "$temp_output_file" # Π Π°Π·ΠΌΠ΅Ρ€ Π΄ΠΎ сТатия local original_size original_size=$(get_file_size "$input_file") # Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ pngquant if ! pngquant --quality=90-100 --speed 1 --output "$temp_output_file" --force "$input_file"; then local error_msg="Ошибка ΠΏΡ€ΠΈ сТатии $input_file с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ pngquant" log_error "$error_msg" echo "$error_msg" > "$error_file" rm -f "$temp_output_file" return 1 fi # Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ оптимизация с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ zopflipng if ! zopflipng -y "$temp_output_file" "$temp_output_file"; then local error_msg="Ошибка ΠΏΡ€ΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ $temp_output_file с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ zopflipng" log_error "$error_msg" echo "$error_msg" > "$error_file" rm -f "$temp_output_file" return 1 fi # Π Π°Π·ΠΌΠ΅Ρ€ послС сТатия local new_size new_size=$(get_file_size "$temp_output_file") # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°, Ρ‡Ρ‚ΠΎ original_size Π½Π΅ Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ if [ "$original_size" -eq 0 ]; then local error_msg="Ошибка: Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° Ρ€Π°Π²Π΅Π½ 0 для $input_file" log_error "$error_msg" echo "$error_msg" > "$error_file" rm -f "$temp_output_file" return 1 fi # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°, ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΠ»ΡΡ Π»ΠΈ Ρ€Π°Π·ΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»Π° if [ "$new_size" -ge "$original_size" ]; then log_success "Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ Π½Π΅ ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΠ»ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»Π° $input_file, пропускаСм сохранСниС" # БохраняСм Ρ…Π΅Ρˆ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ» снова echo "$current_hash" > "$hash_file" rm -f "$temp_output_file" return fi # ΠŸΡ€ΠΎΡ†Π΅Π½Ρ‚ сТатия local reduction reduction=$(awk "BEGIN {printf \"%.2f\", (($original_size - $new_size) / $original_size) * 100}") log_success "Π‘ΠΆΠ°Ρ‚ PNG Ρ„Π°ΠΉΠ»: $input_file Π½Π° $reduction% ($original_size Π±Π°ΠΉΡ‚ -> $new_size Π±Π°ΠΉΡ‚)" # ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Π΅ΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» Π½Π° мСсто Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ mv "$temp_output_file" "$output_file" # БохраняСм Ρ…Π΅Ρˆ echo "$current_hash" > "$hash_file" } export -f process_png # Ѐункция для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ JPEG Ρ„Π°ΠΉΠ»ΠΎΠ² process_jpeg() { local input_file="$1" local relative_path="${input_file#$IMAGE_DIR/}" local output_file="$COMP_DIR/$relative_path" local output_dir output_dir="$(dirname "$output_file")" mkdir -p "$output_dir" # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ„Π°ΠΉΠ»Π° ошибки local error_file="${output_file}.error" if [ -f "$error_file" ]; then # Π€Π°ΠΉΠ» ошибки сущСствуСт, пропускаСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ return fi # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ…Π΅ΡˆΠ° Ρ„Π°ΠΉΠ»Π° local hash_file="${output_file}.md5" local current_hash current_hash="$(md5sum "$input_file" | awk '{print $1}')" if [ -f "$hash_file" ]; then local previous_hash previous_hash="$(cat "$hash_file")" if [ "$current_hash" == "$previous_hash" ]; then # Π€Π°ΠΉΠ» Π½Π΅ измСнился, Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅ΠΌ return fi fi # Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ local temp_output_file="${output_file}.tmp" cp "$input_file" "$temp_output_file" # Π Π°Π·ΠΌΠ΅Ρ€ Π΄ΠΎ сТатия local original_size original_size=$(get_file_size "$input_file") # Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ mozjpeg if ! cjpeg -quality 95 -progressive -optimize -outfile "$temp_output_file" "$input_file"; then local error_msg="Ошибка ΠΏΡ€ΠΈ сТатии $input_file с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ mozjpeg" log_error "$error_msg" echo "$error_msg" > "$error_file" rm -f "$temp_output_file" return 1 fi # Π Π°Π·ΠΌΠ΅Ρ€ послС сТатия local new_size new_size=$(get_file_size "$temp_output_file") # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°, Ρ‡Ρ‚ΠΎ original_size Π½Π΅ Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ if [ "$original_size" -eq 0 ]; then local error_msg="Ошибка: Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° Ρ€Π°Π²Π΅Π½ 0 для $input_file" log_error "$error_msg" echo "$error_msg" > "$error_file" rm -f "$temp_output_file" return 1 fi # ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°, ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΠ»ΡΡ Π»ΠΈ Ρ€Π°Π·ΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»Π° if [ "$new_size" -ge "$original_size" ]; then log_success "Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ Π½Π΅ ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΠ»ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»Π° $input_file, пропускаСм сохранСниС" # БохраняСм Ρ…Π΅Ρˆ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Ρ„Π°ΠΉΠ» снова echo "$current_hash" > "$hash_file" rm -f "$temp_output_file" return fi # ΠŸΡ€ΠΎΡ†Π΅Π½Ρ‚ сТатия local reduction reduction=$(awk "BEGIN {printf \"%.2f\", (($original_size - $new_size) / $original_size) * 100}") log_success "Π‘ΠΆΠ°Ρ‚ JPEG Ρ„Π°ΠΉΠ»: $input_file Π½Π° $reduction% ($original_size Π±Π°ΠΉΡ‚ -> $new_size Π±Π°ΠΉΡ‚)" # ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Π΅ΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» Π½Π° мСсто Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ mv "$temp_output_file" "$output_file" # БохраняСм Ρ…Π΅Ρˆ echo "$current_hash" > "$hash_file" } export -f process_jpeg # ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° PNG Ρ„Π°ΠΉΠ»ΠΎΠ² find "$IMAGE_DIR" -type f \ -not -path "$COMP_DIR/*" \ ! -name "*-no-comp.*" \ -iname "*.png" -print0 | \ xargs -0 -P "$THREADS" -I {} bash -c 'process_png "$@"' _ {} # ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° JPEG Ρ„Π°ΠΉΠ»ΠΎΠ² find "$IMAGE_DIR" -type f \ -not -path "$COMP_DIR/*" \ ! -name "*-no-comp.*" \ -iregex '.*\.\(jpg\|jpeg\)' -print0 | \ xargs -0 -P "$THREADS" -I {} bash -c 'process_jpeg "$@"' _ {} ``` ## ОписаниС Ρ€Π°Π±ΠΎΡ‚Ρ‹ скрипта ### ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ скрипта - **АвтоматичСскоС сТатиС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ**: скрипт ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ всС PNG ΠΈ JPEG Ρ„Π°ΠΉΠ»Ρ‹ Π² Π·Π°Π΄Π°Π½Π½ΠΎΠΉ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ, Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ Ρ‚Π΅Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Ρ‹ для ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ. - **ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Π°Ρ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°**: ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ всС доступныС ядра процСссора для ускорСния процСсса сТатия. - **ИзбСТаниС ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ**: провСряСт Ρ…Π΅ΡˆΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ², Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΡΠΆΠΈΠΌΠ°Ρ‚ΡŒ ΡƒΠΆΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½Π½Ρ‹Π΅ ΠΈΠ»ΠΈ Π½Π΅ измСнившиСся Ρ„Π°ΠΉΠ»Ρ‹. - **Π›ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅**: записываСт ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½Ρ‹Ρ… опСрациях ΠΈ ΠΎΡˆΠΈΠ±ΠΊΠ°Ρ… Π² Π»ΠΎΠ³-Ρ„Π°ΠΉΠ»Ρ‹. ### Π”Π΅Ρ‚Π°Π»ΠΈ Ρ€Π°Π±ΠΎΡ‚Ρ‹ - **Настройка окруТСния**: - Π”ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ: - `IMAGE_DIR`: основная дирСктория с изобраТСниями (`./images`). - `COMP_DIR`: дирСктория для сохранСния сТатых ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ (`./images/comp`). - **ΠŸΠΎΡ‚ΠΎΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ**: Π‘ΠΊΡ€ΠΈΠΏΡ‚ автоматичСски опрСдСляСт количСство доступных процСссорных ядСр ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΈΡ… для ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. - **Π›ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅**: - Π€Π°ΠΉΠ»Ρ‹ Π»ΠΎΠ³ΠΎΠ²: - `zip_image_compression.log`: ΠΆΡƒΡ€Π½Π°Π» ΡƒΡΠΏΠ΅ΡˆΠ½Ρ‹Ρ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. - `zip_image_error.log`: ΠΆΡƒΡ€Π½Π°Π» ошибок. - Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ логирования: - `log_success`: записываСт ΡƒΡΠΏΠ΅ΡˆΠ½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ. - `log_error`: записываСт ошибки. - **ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ:** - ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ: - Для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° вычисляСтся MD5-Ρ…Π΅Ρˆ. - Если Ρ„Π°ΠΉΠ» Π½Π΅ измСнился с ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° послСднСй ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ, ΠΎΠ½ пропускаСтся. - Если ΠΏΡ€ΠΈ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ Π±Ρ‹Π»Π° ошибка (сущСствуСт Ρ„Π°ΠΉΠ» с Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ΠΌ `.error`), Ρ„Π°ΠΉΠ» пропускаСтся. - Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ PNG (`process_png`): - Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ `pngquant` для сТатия с качСством 90-100 ΠΈ максимальной ΡΡ‚Π΅ΠΏΠ΅Π½ΡŒΡŽ сТатия. - Π”Π°Π»Π΅Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ `zopflipng`. - Π‘Ρ€Π°Π²Π½ΠΈΠ²Π°Π΅Ρ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€ исходного ΠΈ сТатого Ρ„Π°ΠΉΠ»ΠΎΠ²; Ссли Ρ€Π°Π·ΠΌΠ΅Ρ€ Π½Π΅ ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΠ»ΡΡ, сТатый Ρ„Π°ΠΉΠ» Π½Π΅ сохраняСтся. - Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ JPEG (`process_jpeg`): - Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ mozjpeg (`cjpeg`) для сТатия с качСством 95 ΠΈ прогрСссивной Ρ€Π°Π·Π²Π΅Ρ€Ρ‚ΠΊΠΎΠΉ. - Аналогично провСряСт ΡΡ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ сТатия ΠΏΠ΅Ρ€Π΅Π΄ сохранСниСм. - **ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Π°Ρ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°**: - Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ `find` для поиска всСх ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹Ρ… Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ². - ΠŸΡ€ΠΎΠΏΡƒΡΠΊΠ°Π΅Ρ‚ Ρ„Π°ΠΉΠ»Ρ‹, содСрТащиС `-no-comp` Π² Π½Π°Π·Π²Π°Π½ΠΈΠΈ, Π° Ρ‚Π°ΠΊΠΆΠ΅ Ρ„Π°ΠΉΠ»Ρ‹ Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ `comp`. - Команда `xargs` с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ `-P` запускаСт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Π² нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². ## Как ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ скрипт 1. **ΠŸΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ°**: 1. ΠŸΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚Π΅ всС изобраТСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΆΠ°Ρ‚ΡŒ, Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ `./images`. 2. Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ установлСны всС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹. 2. **Запуск скрипта**: 1. Π‘Π΄Π΅Π»Π°ΠΉΡ‚Π΅ скрипт исполняСмым: `chmod +x your_script_name.sh` 3. ЗапуститС скрипт: `./your_script_name.sh` 4. **Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ**: 1. Π‘ΠΆΠ°Ρ‚Ρ‹Π΅ изобраТСния Π±ΡƒΠ΄ΡƒΡ‚ сохранСны Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ `./images/comp`, сохраняя структуру исходной Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ. 2. Π›ΠΎΠ³ΠΈ ΡƒΡΠΏΠ΅ΡˆΠ½Ρ‹Ρ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΈ ошибок ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π² Ρ„Π°ΠΉΠ»Π°Ρ… `zip_image_compression.log` ΠΈ `zip_image_error.log` соотвСтствСнно. ## ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² сТатия ![[../../meta/files/images/Pasted image 20240925150631.png]] ## Nginx Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ Π½Π°ΡƒΡ‡ΠΈΠΌ nginx ΠΏΡ€ΠΈ запросС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ сначала ΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ ΠΎΡ‚Π΄Π°Ρ‚ΡŒ сТатоС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΈ Ссли Π΅Π³ΠΎ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚, Ρ‚ΠΎ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»: ```nginx location ~* ^(/blog/ru/content/images/)(.+)\.(png|jpe?g)$ { expires 1d; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; root /var/site/images; try_files /comp/$2.$3 $uri =404; } ``` *** ## ΠœΠ΅Ρ‚Π° информация **ΠžΠ±Π»Π°ΡΡ‚ΡŒ**:: [[../../meta/zero/00 Π‘Π½ΠΈΠΏΠ΅Ρ‚Ρ‹ Π½Π° bash|00 Π‘Π½ΠΈΠΏΠ΅Ρ‚Ρ‹ Π½Π° bash]] **Π ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒ**:: [[../fundamental/Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ…|Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ…]] **Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ**:: **Автор**:: **Π‘ΠΎΠ·Π΄Π°Π½Π°**:: [[2023-11-20]] ### Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ - [ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π² Webp](ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅%20ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ%20Π²%20Webp.md) ### Π”ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ