Blog >> Whitepapers >> Wordpress.

워드프레스 업데이트 및 cron 관리 150 150 phobe

워드프레스 업데이트 및 cron 관리

워드프레스 사이트 건강 부분에서 양호 하다는 결과를 받지 못하는 항목에서
1. 백그라운드 업데이트가 예상대로 작동하지 않는다는 문제.
2. 캐시가 감지되지 않는다는 문제.
3. OP캐시 문제(‘오퍼코드 캐시’ 로 리포팅 하네요).

일단 백그라운드 업데이트 문제
이건 selinux 적용 문제로 사이트 전체가 http 방식으로 쓰기가 허용 되지 않기 때문. 물론 FTP를 열고 FTP 관련 컨택스트 를 적용한다면 문제가 해결 될 수도 있지만, FTP를 열어두지 않았음. 그래서 터미널에서 wp cli 를 이용하기로 함.
보안과 마이너 업데이트에는 메이저 업데이트를 쓰지 않기로 함. 메이저 업데이트는 –major 옵션을 추가함.

1. 먼저 업데이트 쉘 스크립트 작성

~]# wp --version # 먼저 버전확인 후 wp-cli 유무 확인
WP-CLI 2.12.0

# 시스템 타이머를 이용한 워드프레스 업데이트 쉘스크립트 생성
# 로그는 내계정의 logs폴더에 저장 7일 이전의 로그는 삭제
~]# vi /usr/local/bin/update_wp_core.sh
#!/bin/bash

# 인자 확인
DOMAIN=$1
if [ -z "$DOMAIN" ]; then
    echo "도메인 이름이 필요합니다."
    exit 1
fi

# 로그 설정 (요청하신 하이픈 형식)
LOG_DIR="/home/phobe/logs"
DATE=$(date +%Y-%m-%d)
LOG_FILE="$LOG_DIR/wp-update_${DOMAIN}_${DATE}.log"

# 스크립트 내에서 로그를 직접 출력
exec >> "$LOG_FILE" 2>&1

echo "=== $(date) 보안/마이너 업데이트 시작: $DOMAIN ==="

# 업데이트 수행
/usr/local/bin/wp core update --path="/host/$DOMAIN/public_html" --force

if [ $? -eq 0 ]; then
    echo "Success: $DOMAIN"
else
    echo "Failed: $DOMAIN"
fi

echo "=== $(date) 업데이트 종료 ==="

# 로그 정리 (해당 도메인의 7일 지난 로그 삭제)
find "$LOG_DIR" -name "wp-update_${DOMAIN}_*.log" -type f -mtime +7 -delete

echo "로그 정리 완료 (7일 이상 경과된 파일 삭제)" >> $LOG_FILE

2. 서비스 탬플릿 파일 및 타이머 탬플릿 파일 생성

~]# vi /etc/systemd/system/custom-update-wp-core\@.service
[Unit]
Description=Custom WordPress Core Update Service for %i
After=network.target

[Service]
Type=oneshot
User=phobe # 요 부분이 매우 중요. 호스트 디렉토리 소유자 일반 유저로 타이머 실행.
# root 소유 스크립트를 phobe가 실행(711 권한)
ExecStart=/usr/local/bin/update_wp_core.sh %i
# 스크립트 내부에서 로그를 처리하므로 여기는 비워두거나 간단히 지정
StandardOutput=null
StandardError=journal

[Install]
WantedBy=multi-user.target

########## 이상 서비스 파일 템플릿 ##########

~]# vi /etc/systemd/system/custom-update-wp-core\@.timer
[Unit]
Description=Weekly WordPress Update Timer for %i

[Timer]
OnCalendar=Sun *-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

########## 이상 타이머 파일 템플릿 ##########

3. 그리고, 적용을 위한 데몬 리로드

~]# systemctl daemon-reload

4. 그리고 가상 호스트 사이트가 추가 될 때마다, 호스트를 위한 서비스 활성화 심볼릭 링크를 생성스케줄 확인

~]# systemctl enable --now custom-update-wp-core@[호스트명].timer
Created symlink '/etc/systemd/system/timers.target.wants/custom-update-wp-core@[호스트명].timer'  '/etc/systemd/system/custom-update-wp-core@.timer'.

# 그리고 워드프레스 업데이트를 위한 스케줄 확인
~]# systemctl list-timers --all | grep custom-update-wp-core
Sun 2026-06-14 03:00:00 KST   2 days -                                      - custom-update-wp-core@gldigital.co.kr.timer custom-update-wp-core@gldigital.co.kr.service
Sun 2026-06-14 03:00:00 KST   2 days -                                      - custom-update-wp-core@yjco.kr.timer         custom-update-wp-core@yjco.kr.service

# 업데이트 스크립트 실행이 2일 남음. 오늘이 11일 목요일 - 타이머에 일요일 3시에 하라고 했으니, "Sun 2026-06-14 03:00:00 KST" 에 한다고 함.

워드프레스 메이저 업데이트는 3~4개월 마다 있다고 하니 wp-cli 를 직접 실행. 디비 및 플러그인 호환성 고려해서 수동으로 실행 시키는 것으로 결정.

# --major 옵션을 추가
~]$ wp core update --major --path="/host/[가상호스트 디렉토리]/public_html" --force

5. 그리고, 테마 펑션 파일에 다음의 코드로 업데이트 보고를 비활성화

// 백그라운드 업데이트 관련 사이트 상태 경고 숨기기
add_filter( 'site_status_tests', function( $tests ) {
    unset( $tests['async']['background_updates'] );
    return $tests;
} );

마찬가지로 wp-cron 을 타이머로 관리합니다.

# 1. wp-config.php 파일에 define('DISABLE_WP_CRON', true);
# 를추가하여 기존의 느린 크론을 끕니다.
~]$ vi wp-config
// 내부 스케줄링 작업인 WP-Cron을 실행하지 않도록 설정.
// 대신 시스템 크론이나 외부 스케줄러를 통해 WP-Cron 작업을 실행해야함.
// WP-Cron은  사이트의 트래픽이 있을 때마다 실행되는데,
//  설정을 사용하면 트래픽이 없는 경우에도 WP-Cron이 실행되지 않음.
// 리얼크론 사용시. 시스템 타이머에 custom-update-wp-cron 으로 대치.
define('DISABLE_WP_CRON', true);

# 2. WP-Cron 전용 서비스 및 타이머 생성
# 서비스 파일: /etc/systemd/system/custom-update-wp-cron@.service
~]# vi /etc/systemd/system/custom-update-wp-cron@.service
[Unit]
Description=WordPress Cron for %i
After=network.target

[Service]
Type=oneshot
User=phobe
# WP-CLI를 사용하여 예약된 이벤트만 실행
ExecStart=/usr/local/bin/wp cron event run --due-now --path=/host/%i/public_html

# 타이머 파일: /etc/systemd/system/custom-update-wp-cron@.timer
~]# vi /etc/systemd/system/custom-update-wp-cron@.timer
[Unit]
Description=Run WordPress Cron every 15 minutes for %i

[Timer]
# 30분마다 실행 (사용량에 따라 5분~1시간 조절 가능)
OnCalendar=*:0/30
Persistent=true

[Install]
WantedBy=timers.target

# 3. 데몬리로드
~]# systemctl daemon-reload

# 4. 사이트별로 타이머 추가
~]# systemctl enable --now custom-update-wp-cron@gldigital.co.kr.timer

# 5. 타이머 스케줄 확인
~]$ systemctl list-timers --all | grep custom-update-wp-cron
Thu 2026-07-09 15:00:00 KST  3min 6s -                                      - custom-update-wp-cron@gldigital.co.kr.timer custom-update-wp-cron@gldigital.co.kr.service
Thu 2026-07-09 15:00:00 KST  3min 6s -                                      - custom-update-wp-cron@tv.dhgb.co.kr.timer   custom-update-wp-cron@tv.dhgb.co.kr.service
Thu 2026-07-09 15:00:00 KST  3min 6s -                                      - custom-update-wp-cron@yjco.kr.timer         custom-update-wp-cron@yjco.kr.service

# 6. 크론 주기 확인
~]$ wp cron event list --path=/host/surfnsnow.kr/public_html
+-----------------------------------------+---------------------+-----------------------+------------+
| hook                                    | next_run_gmt        | next_run_relative     | recurrence |
+-----------------------------------------+---------------------+-----------------------+------------+
| recovery_mode_clean_expired_keys        | 2026-08-10 07:03:14 | 26 minutes 44 seconds | 1 day      |
| wp_version_check                        | 2026-08-10 07:03:14 | 26 minutes 44 seconds | 12 hours   |
| wp_update_plugins                       | 2026-08-10 07:03:14 | 26 minutes 44 seconds | 12 hours   |
| wp_update_themes                        | 2026-08-10 07:03:14 | 26 minutes 44 seconds | 12 hours   |
| wp_privacy_delete_old_export_files      | 2026-08-10 07:03:14 | 26 minutes 44 seconds | 1 hour     |
| wp_scheduled_delete                     | 2026-08-10 07:09:00 | 32 minutes 30 seconds | 1 day      |
| delete_expired_transients               | 2026-08-10 07:09:00 | 32 minutes 30 seconds | 1 day      |
| wp_update_user_counts                   | 2026-08-10 07:09:00 | 32 minutes 30 seconds | 12 hours   |
| wp_scheduled_auto_draft_delete          | 2026-08-10 07:09:05 | 32 minutes 35 seconds | 1 day      |
| wp_delete_temp_updater_backups          | 2026-08-10 07:10:06 | 33 minutes 36 seconds | 1 week     |
| wp_queue_connections_databaseconnection | 2026-08-10 07:36:30 | 1 hour                | 1 min     |
| wp_site_health_scheduled_check          | 2026-08-11 07:03:14 | 1 day                 | 1 week     |
+-----------------------------------------+---------------------+-----------------------+------------+

# 여기서 특정 후크가 실행되는 주기가 맘에 안든다.
# wp_queue_connections_databaseconnection 1분 이네요. 이걸 1시간으로 
# 뽀나스로 외부 폰트 로딩도 걍 무시하기.
# 차일드테마 functions.php
/*
 * wp_queue_connections_databaseconnection 크론 주기를 1분에서 1시간(hourly)으로 강제 변경
 */
add_action('init', function () {
    $hook = 'wp_queue_connections_databaseconnection';

    // 현재 등록된 다음 실행 타임스탬프 확인
    $timestamp = wp_next_scheduled($hook);

    // 스케줄이 등록되어 있다면
    if ($timestamp) {
        $schedule = wp_get_schedule($hook);

        // 만약 주기가 'hourly' 아니라면 (1분  다른 주기인 경우)
        if ('hourly' !== $schedule) {
            // 기존 1분짜리 스케줄 제거
            wp_unschedule_event($timestamp, $hook);

            // 1시간 주기(hourly) 재등록
            wp_schedule_event(time() + 3600, 'hourly', $hook);
        }
    } else {
        // 혹시 스케줄이 없다면 1시간   실행되도록 정식 등록
        wp_schedule_event(time() + 3600, 'hourly', $hook);
    }
}, 10);

/*
 * 외부 폰트 제거 2단계
 * 1. 외부 구글 폰트 로딩 핸들 완전 제거 (Dequeue)
 */
add_action('wp_enqueue_scripts', function () {
    // Brooklyn 테마  빌더가 불러오는 외부 폰트 핸들 해제
    wp_dequeue_style('open-sans');
    wp_dequeue_style('google-fonts');
    wp_dequeue_style('ut-google-fonts');
    wp_deregister_style('open-sans');
    wp_deregister_style('google-fonts');
}, 999);

/*
 * 2. HTML 내부에 남아있는 googleapis.com/css 프리로드/링크 태그 강제 제거
 */
add_filter('style_loader_tag', function ($html, $handle) {
    if (false !== strpos($html, 'fonts.googleapis.com')) {
        return ''; // 구글 폰트 관련 link 태그를 빈값으로 지워버림
    }

    return $html;
}, 999, 2);