mycpen

Mycpen

记录学习历程与受益知识
github
telegram
bilibili

01_PHP-CentOS8.2 Compile and Install PHP8.1.10

I. Introduction#

Due to the failure of https://www.jsdelivr.com/, the blogger plans to back up the image hosting on GitHub to other platforms.

Seeing Lsky Image Hosting online sparked the idea of building a self-hosted image hosting service, which requires PHP >= 8.0.2, so I planned to compile and install PHP.

Ultimately, I gave up due to the server's low configuration (1 core 2G) causing the compilation to fail. I then turned to the Youpai Cloud platform, where I had already set up the environment.

Blog content: PHP-CentOS8.2 Compile and Install PHP8.1.10 + Write a script to migrate GitHub image hosting to Youpai Cloud (ftp) + Write a script to batch modify article content

II. Main Content#

2.1❤ Compile and Install PHP8.1.10 on CentOS8.2#

2.1.1 Download PHP8 and oniguruma source code and upload it to the server's /mnt directory

https://www.php.net/distributions/php-8.1.10.tar.gz

https://codeload.github.com/kkos/oniguruma/tar.gz/refs/tags/v6.9.4

# Extract
tar xzf oniguruma-6.9.4.tar.gz
tar xzf php-8.1.10.tar.gz

2.1.2 Install PHP8 dependencies

# 2 Install PHP8 dependencies
yum -y install autoconf freetype gd libpng libpng-devel libjpeg libxml2 libxml2-devel zlib curl curl-devel net-snmp-devel libjpeg-devel php-ldap openldap-devel openldap-clients freetype-devel gmp-devel libzip libzip-devel sqlite-devel automake libtool

2.1.3 Compile the PHP8 dependency package oniguruma

# 3.1 Generate configure
cd /mnt/oniguruma-6.9.4
./autogen.sh

# 3.2 Generate compilation configuration file
./configure --prefix=/usr

# 3.3 Compile and install
make && make install

2.1.4 Compile the main PHP8 package

# 4.1 Generate compilation configuration file
cd /mnt/php-8.1.10
./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx --enable-mysqlnd --with-mysqli --with-pdo-mysql --enable-opcache --with-pcre-jit --enable-gd --with-jpeg --with-freetype --with-gettext --with-curl --with-openssl --enable-sockets --enable-mbstring --enable-xml --with-zip --with-zlib --with-snmp --with-mhash --enable-ftp --enable-bcmath --enable-soap --enable-shmop --enable-sysvsem --enable-pcntl --with-gmp

# 4.2 Compile and install
make && make install

Due to low configuration, the compilation failed.

2.1.5 Directory after compilation and installation

/usr/local/php

References

https://www.bilibili.com/read/cv9248283/

2.2 Migrate GitHub Image Hosting to Youpai Cloud via FTP#

References

Official Video Tutorial - Create Storage Service and Use FTP Upload You can get the username and password

The application for Youpai Cloud storage service has been completed + binding a custom domain https://help.upyun.com/knowledge-base/quick_start/

2.2.1 Write a Python script for batch processing

Source from http://blog.csdn.net/ouyang_peng/article/details/79271113

#!/usr/bin/python
# -*- coding: UTF-8 -*-


from cmath import log
from ftplib import FTP
import os
import sys
import time
import socket
import subprocess

class MyFTP:
    """
        FTP automatic download and upload script, can operate recursively on directories
        Author: Ouyang Peng
        Blog address: http://blog.csdn.net/ouyang_peng/article/details/79271113
    """

    def __init__(self, host, port=21):
        """ Initialize FTP client
        Parameters:
                 host: IP address

                 port: Port number
        """
        # print("__init__()---> host = %s ,port = %s" % (host, port))

        self.host = host
        self.port = port
        self.ftp = FTP()
        # Reset encoding
        #self.ftp.encoding = 'gbk'
        self.ftp.encoding = 'utf8'
        # Get script path
        path = os.path.dirname(os.path.realpath(__file__))
        self.log_file = open(path + "/log.txt", "a", encoding='utf-8')
        self.file_list = []

    def login(self, username, password):
        """ Initialize FTP client
            Parameters:
                  username: Username

                 password: Password
            """
        try:
            timeout = 60
            socket.setdefaulttimeout(timeout)
            # 0 active mode 1 passive mode
            self.ftp.set_pasv(True)
            # Open debug level 2 to show detailed information
            # self.ftp.set_debuglevel(2)

            self.debug_print('Starting to connect to %s' % self.host)
            self.ftp.connect(self.host, self.port)
            self.debug_print('Successfully connected to %s' % self.host)

            self.debug_print('Starting to log in to %s' % self.host)
            self.ftp.login(username, password)
            self.debug_print('Successfully logged in to %s' % self.host)

            self.debug_print(self.ftp.welcome)
        except Exception as err:
            self.deal_error("FTP connection or login failed, error description: %s" % err)
            pass

    def is_same_size(self, local_file, remote_file):
        """Check if the sizes of the remote file and local file are the same

           Parameters:
             local_file: Local file

             remote_file: Remote file
        """
        try:
            remote_file_size = self.ftp.size(remote_file)
        except Exception as err:
            # self.debug_print("is_same_size() error description: %s" % err)
            remote_file_size = -1

        try:
            local_file_size = os.path.getsize(local_file)
        except Exception as err:
            # self.debug_print("is_same_size() error description: %s" % err)
            local_file_size = -1

        self.debug_print('local_file_size:%d  , remote_file_size:%d' % (local_file_size, remote_file_size))
        if remote_file_size == local_file_size:
            return 1
        else:
            return 0

    def download_file(self, local_file, remote_file):
        """Download file from FTP
            Parameters:
                local_file: Local file

                remote_file: Remote file
        """
        self.debug_print("download_file()---> local_path = %s ,remote_path = %s" % (local_file, remote_file))

        if self.is_same_size(local_file, remote_file):
            self.debug_print('%s file size is the same, no need to download' % local_file)
            return
        else:
            try:
                self.debug_print('>>>>>>>>>>>>Downloading file %s ... ...' % local_file)
                buf_size = 1024
                file_handler = open(local_file, 'wb')
                self.ftp.retrbinary('RETR %s' % remote_file, file_handler.write, buf_size)
                file_handler.close()
            except Exception as err:
                self.debug_print('Error downloading file, exception: %s ' % err)
                return

    def download_file_tree(self, local_path, remote_path):
        """Download multiple files from the remote directory to the local directory
                       Parameters:
                         local_path: Local path

                         remote_path: Remote path
                """
        print("download_file_tree()--->  local_path = %s ,remote_path = %s" % (local_path, remote_path))
        try:
            self.ftp.cwd(remote_path)
        except Exception as err:
            self.debug_print('Remote directory %s does not exist, continuing...' % remote_path + " ,specific error description: %s" % err)
            return

        if not os.path.isdir(local_path):
            self.debug_print('Local directory %s does not exist, creating local directory first' % local_path)
            os.makedirs(local_path)

        self.debug_print('Switched to directory: %s' % self.ftp.pwd())

        self.file_list = []
        # Method callback
        self.ftp.dir(self.get_file_list)

        remote_names = self.file_list
        self.debug_print('Remote directory list: %s' % remote_names)
        for item in remote_names:
            file_type = item[0]
            file_name = item[1]
            local = os.path.join(local_path, file_name)
            if file_type == 'd':
                print("download_file_tree()---> Downloading directory: %s" % file_name)
                self.download_file_tree(local, file_name)
            elif file_type == '-':
                print("download_file()---> Downloading file: %s" % file_name)
                self.download_file(local, file_name)
        self.ftp.cwd("..")
        self.debug_print('Returned to upper directory %s' % self.ftp.pwd())
        return True

    def upload_file(self, local_file, remote_file):
        """Upload file from local to FTP

           Parameters:
             local_path: Local file

             remote_path: Remote file
        """
        if not os.path.isfile(local_file):
            self.debug_print('%s does not exist' % local_file)
            return

        if self.is_same_size(local_file, remote_file):
            self.debug_print('Skipping equal file: %s' % local_file)
            return

        buf_size = 1024
        file_handler = open(local_file, 'rb')
        self.ftp.storbinary('STOR %s' % remote_file, file_handler, buf_size)
        file_handler.close()
        self.debug_print('Uploaded: %s' % local_file + " successfully!")

    def upload_file_tree(self, local_path, remote_path):
        """Upload multiple files from the local directory to FTP
           Parameters:

             local_path: Local path

             remote_path: Remote path
        """
        if not os.path.isdir(local_path):
            self.debug_print('Local directory %s does not exist' % local_path)
            return

        self.ftp.cwd(remote_path)
        self.debug_print('Switched to remote directory: %s' % self.ftp.pwd())

        local_name_list = os.listdir(local_path)
        for local_name in local_name_list:
            src = os.path.join(local_path, local_name)
            if os.path.isdir(src):
                try:
                    self.ftp.mkd(local_name)
                except Exception as err:
                    self.debug_print("Directory already exists %s ,specific error description: %s" % (local_name, err))
                self.debug_print("upload_file_tree()---> Uploading directory: %s" % local_name)
                self.upload_file_tree(src, local_name)
            else:
                self.debug_print("upload_file_tree()---> Uploading file: %s" % local_name)
                self.upload_file(src, local_name)
        self.ftp.cwd("..")

    def close(self):
        """ Exit FTP
        """
        self.debug_print("close()---> Exiting FTP")
        self.ftp.quit()
        self.log_file.close()

    def debug_print(self, s):
        """ Print log
        """
        self.write_log(s)

    def deal_error(self, e):
        """ Handle error exceptions
            Parameters:
                e: Exception
        """
        log_str = 'An error occurred: %s' % e
        self.write_log(log_str)
        sys.exit()

    def write_log(self, log_str):
        """ Record log
            Parameters:
                log_str: Log
        """
        time_now = time.localtime()
        date_now = time.strftime('%Y-%m-%d', time_now)
        format_log_str = "%s ---> %s \n " % (date_now, log_str)
        print(format_log_str)
        self.log_file.write(format_log_str)

    def get_file_list(self, line):
        """ Get file list
            Parameters:
                line:
        """
        file_arr = self.get_file_name(line)
        # Remove . and ..
        if file_arr[1] not in ['.', '..']:
            self.file_list.append(file_arr)

    def get_file_name(self, line):
        """ Get file name
            Parameters:
                line:
        """
        pos = line.rfind(':')
        while (line[pos] != ' '):
            pos += 1
        while (line[pos] == ' '):
            pos += 1
        file_arr = [line[0], line[pos:]]
        return file_arr


if __name__ == "__main__":
    # Clear log
    path = os.path.dirname(os.path.realpath(__file__))      # Script path
    if os.path.exists(path + '/log.txt'):
        log_file = path + '/log.txt 'if os.sep == "/" else path + '\\' + 'log.txt'
        subprocess.Popen(f'rm -rf {log_file}', shell=True)
        time.sleep(1)

    my_ftp = MyFTP("xxx.ftp.upyun.com")
    my_ftp.login("xxx/xxx", "xxx")


    # Download a single file
    # my_ftp.download_file("E:/code_zone/image_bed/image/wallpaper/1.jpg", "/image/wallpaper/1.jpg")

    # Upload a single file
    # my_ftp.upload_file("G:/ftp_test/Release/XTCLauncher.apk", "/App/AutoUpload/ouyangpeng/I12/Release/XTCLauncher.apk")

    # Download directory
    # image.cpen.top/image/ → Local E:/code_zone/image_bed/image/    (Local image hosting directory, Youpai Cloud path)
    if os.sep == "\\":
        my_ftp.download_file_tree("E:/code_zone/image_bed/image/", "/image/")
    elif os.sep == "/":     # aliyun
        my_ftp.download_file_tree("/root/code_zone/image_bed/image/", "/image/")

    # Upload directory
    # Local E:/code_zone/image_bed/image/ → image.cpen.top/image/    (Local image hosting directory, Youpai Cloud path)
    if os.sep == "\\":      # Windows
        my_ftp.upload_file_tree("E:/code_zone/image_bed/image/", "/image/")    
        my_ftp.close()
    elif os.sep == "/":     # aliyun
        my_ftp.upload_file_tree("/root/code_zone/image_bed/image/", "/image/")  
        my_ftp.close()


# Command
# python E:/code_zone/tools/python-ftp/ftp.py
# python3 /root/code_zone/tools/python-ftp/ftp.py

2.2.2 Explanation

my_ftp.login("Username xxx/xxx", "Password xxx") Reference https://techs.upyun.com/videos/cdnpage/creating_storage.html

Later, the script will be uploaded to the cloud server, and through a scheduled task, it will sync every 15 minutes to keep GitHub and Youpai Cloud image hosting consistent.

# root @ CentOS in ~ [18:05:59]
$ crontab -l
*/15 * * * *  cd /root/code_zone/image_bed/; git pull; python3 /root/code_zone/tools/python-ftp/ftp.py; bash git.sh

After migrating the image hosting, when calling image resources in the blog, the browser automatically jumps from http to https, causing the images to fail due to the lack of a certificate, so I applied for an SSL certificate and uploaded it to Youpai Cloud.

image-20220910180219146

2.3 Write a script to batch modify article content#

Source reference https://blog.csdn.net/qq_38150250/article/details/118026219

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# Source reference  https://blog.csdn.net/qq_38150250/article/details/118026219

import os
import re

# File search find . -name file_name -type f
# Search function: search_path search root path 

# Get article path
def search(search_path, search_result):
    # Get all files in the current path
    all_file = os.listdir(search_path)
    # For each file
    for each_file in all_file:
        # If the file is a directory
        if os.path.isdir(search_path + each_file):
            # Recursively search
            search(search_path + each_file + '/', search_result)
        # If it is a file to be searched
        else:
            if re.findall('.*\.md$', each_file) == [each_file]:
            # Output path
                search_result.append(search_path + each_file)


# Replace sed -i 's/old_str/new_str/'
# Text replacement replace_file_name file path to be replaced, replace_old_str character to be replaced, replace_new_str new character
def replace(replace_file_name, replace_old_str, replace_new_str):
    with open(replace_file_name, "r", encoding = "UTF-8") as f1: 
        content = f1.read()
        f1.close()
        t = content.replace(replace_old_str, replace_new_str)
    with open(replace_file_name, "w", encoding = "UTF-8") as f2:
        f2.write(t)
    f2.close()


# Places that need to be changed
#path = 'E:/code_zone/.history/20220831_blog/source/_posts/'
path_list = [
    'E:/code_zone/hexo-source/source/_posts/',
    'E:/code_zone/hexo-source-butterfly/source/_posts/',
    'E:/code_zone/hexo-source-diary/source/_posts/',
]
old_str = 'https://image.cpen.top/image/'
new_str = 'https://image.cpen.top/image/'
search_result = []

if __name__ == '__main__':
    result = []                 # Store file paths
    # Default current directory
    # path = os.getcwd()
    for path in path_list:
        search(path, result)    # Get article paths
    count = 0
    for file_name in result:
        replace(file_name, old_str, new_str)
        count += 1
        print("{} done  {}".format(file_name, count))

# Command
# python E:/code_zone/tools/python-replace/replace.py

2.3.1 Explanation

search function specifies the file type as .md, which can obtain the complete path of the article;

path_list list stores the parent directory paths of the articles to be modified, which can recursively query subdirectories;

old_str content to be replaced

new_str new content

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.