杰瑞科技汇

Python如何直接修改Linux系统时间?

在 Python 中修改 Linux 系统时间,核心思想是:Python 本身没有直接修改系统时间的权限,它必须通过调用系统命令(如 datetimedatectl)来实现

Python如何直接修改Linux系统时间?-图1
(图片来源网络,侵删)

直接使用 os.system()subprocess 模块来执行这些命令是常见的方法。普通用户通常没有权限修改系统时间,需要使用 sudo 权限。

下面我将介绍几种方法,并重点讲解最推荐、最安全的现代方法。


⚠️ 重要前提:权限问题

在 Linux 系统中,修改系统时间是受严格控制的操作,你需要:

  1. 使用 sudo:你的 Python 脚本必须以 root 权限运行。
  2. 正确的用户:确保运行脚本的用户在 sudoers 文件中,并且可以无需密码或使用密码来执行特定的命令(/bin/date)。

使用 subprocess 模块(推荐)

这是最现代、最灵活、最安全的方式。subprocess 模块是 Python 官方推荐的用于创建子进程的接口。

Python如何直接修改Linux系统时间?-图2
(图片来源网络,侵删)

使用 timedatectl(适用于现代 systemd 系统,如 Ubuntu 16+, CentOS 7+)

timedatectlsystemd 的一部分,是控制时间和日期的推荐工具,它更结构化,能更好地处理硬件时钟和 NTP 同步。

示例代码:

import subprocess
import sys
def set_system_time(new_time_str):
    """
    使用 timedatectl 设置系统时间。
    new_time_str: 必须是 "YYYY-MM-DD HH:MM:SS" 格式的字符串。
    """
    try:
        # 构建命令
        # 注意:需要 root 权限
        command = ['sudo', 'timedatectl', 'set-time', new_time_str]
        # 执行命令
        print(f"Executing command: {' '.join(command)}")
        process = subprocess.run(command, check=True, capture_output=True, text=True)
        print("系统时间设置成功!")
        print(process.stdout)
        return True
    except subprocess.CalledProcessError as e:
        print(f"设置时间失败!错误码: {e.returncode}", file=sys.stderr)
        print(f"错误信息: {e.stderr}", file=sys.stderr)
        return False
    except FileNotFoundError:
        print("错误: 'timedatectl' 命令未找到,请确保您在使用 systemd 的系统上。", file=sys.stderr)
        return False
# --- 使用示例 ---
if __name__ == "__main__":
    # 设置一个新时间,2025-10-27 15:30:00
    new_time = "2025-10-27 15:30:00"
    if set_system_time(new_time):
        print(f"当前系统时间已更新为: {new_time}")
    else:
        print("时间更新失败。")

如何运行:

# 必须使用 sudo 运行 Python 脚本
sudo python3 your_script_name.py

优点:

Python如何直接修改Linux系统时间?-图3
(图片来源网络,侵删)
  • 现代标准systemd 生态系统的首选工具。
  • 功能强大:除了设置时间,还可以设置时区、控制 NTP 等。
  • 状态清晰:命令本身有明确的成功/失败返回值。

使用 date 命令(传统方法)

date 命令非常通用,几乎所有 Linux 发行版都支持,但直接使用 date 设置时间有时会被系统服务(如 ntpchronyd)覆盖。

示例代码:

import subprocess
import sys
def set_system_time_with_date(new_time_str):
    """
    使用 date 命令设置系统时间。
    new_time_str: 必须是 "MMDDHHMMYYYY" 或 "YYYY-MM-DD HH:MM:SS" 格式。
    注意:格式取决于系统的 date 命令版本。
    """
    try:
        # 构建命令
        # 注意:需要 root 权限
        # 格式1: "MMDDHHMMYYYY" ( 102715302025)
        # 格式2: "YYYY-MM-DD HH:MM:SS" (更直观)
        command = ['sudo', 'date', '-s', new_time_str]
        # 执行命令
        print(f"Executing command: {' '.join(command)}")
        process = subprocess.run(command, check=True, capture_output=True, text=True)
        print("系统时间设置成功!")
        # date 命令通常没有标准输出,print(process.stdout) 可能是空的
        return True
    except subprocess.CalledProcessError as e:
        print(f"设置时间失败!错误码: {e.returncode}", file=sys.stderr)
        print(f"错误信息: {e.stderr}", file=sys.stderr)
        return False
    except FileNotFoundError:
        print("错误: 'date' 命令未找到。", file=sys.stderr)
        return False
# --- 使用示例 ---
if __name__ == "__main__":
    # 使用更直观的格式
    new_time = "2025-10-27 15:30:00"
    if set_system_time_with_date(new_time):
        print(f"当前系统时间已更新为: {new_time}")
    else:
        print("时间更新失败。")

如何运行:

# 必须使用 sudo 运行 Python 脚本
sudo python3 your_script_name.py

注意:

  • date -s 的格式可能因系统而异。YYYY-MM-DD HH:MM:SS 是最通用的。
  • 如果系统运行着 NTP 服务,它会立即将你设置的时间同步掉,你可能需要先停止 NTP 服务。

使用 os.system(不推荐,仅作了解)

这是较老的方法,功能简单,但不如 subprocess 安全和灵活。

import os
import sys
def set_time_with_os_system(new_time_str):
    """
    使用 os.system 设置时间。
    """
    command = f'sudo date -s "{new_time_str}"'
    print(f"Executing command: {command}")
    exit_code = os.system(command)
    if exit_code == 0:
        print("系统时间设置成功!")
        return True
    else:
        print(f"设置时间失败!错误码: {exit_code}", file=sys.stderr)
        return False
# --- 使用示例 ---
if __name__ == "__main__":
    new_time = "2025-10-27 15:30:00"
    if set_time_with_os_system(new_time):
        print(f"当前系统时间已更新为: {new_time}")
    else:
        print("时间更新失败。")

为什么不推荐?

  • 安全风险new_time_str 变量来自不可信的输入,可能会导致命令注入攻击(如果输入是 "; rm -rf /;")。
  • 功能有限:难以处理命令的输出和错误。
  • 已过时subprocess 是其替代品,设计更完善。

完整的最佳实践示例

下面是一个结合了 timedatectl 并处理了 NTP 服务的完整脚本,这在生产环境中非常有用。

import subprocess
import sys
import time
def stop_ntp_service():
    """尝试停止 ntpd 或 chronyd 服务"""
    services_to_stop = ['chronyd', 'ntpd']
    for service in services_to_stop:
        try:
            print(f"尝试停止服务: {service}")
            subprocess.run(['sudo', 'systemctl', 'stop', service], check=True, capture_output=True)
            print(f"成功停止服务: {service}")
            return True
        except subprocess.CalledProcessError:
            continue # 尝试下一个服务
    print("警告: 未找到或无法停止 NTP 服务,时间同步可能会覆盖设置。")
    return False
def set_system_time_safely(new_time_str):
    """
    安全地设置系统时间:先停止 NTP,再设置时间。
    """
    # 1. 停止 NTP 服务
    stop_ntp_service()
    # 2. 设置时间
    try:
        command = ['sudo', 'timedatectl', 'set-time', new_time_str]
        print(f"Executing command: {' '.join(command)}")
        subprocess.run(command, check=True, capture_output=True, text=True)
        print("系统时间设置成功!")
        return True
    except subprocess.CalledProcessError as e:
        print(f"设置时间失败!错误码: {e.returncode}", file=sys.stderr)
        print(f"错误信息: {e.stderr}", file=sys.stderr)
        return False
if __name__ == "__main__":
    # 设置一个新时间
    new_time = "2025-10-27 15:30:00"
    print(f"准备将系统时间设置为: {new_time}")
    if set_system_time_safely(new_time):
        # 验证时间是否已更改
        verify_cmd = ['timedatectl', 'status']
        result = subprocess.run(verify_cmd, capture_output=True, text=True)
        print("\n--- 验证当前系统时间状态 ---")
        print(result.stdout)
    else:
        print("时间更新失败。")
方法 命令 优点 缺点 推荐度
subprocess + timedatectl sudo timedatectl set-time ... 现代、安全、功能强大、推荐 需要了解 systemd ⭐⭐⭐⭐⭐
subprocess + date sudo date -s ... 通用、简单 可能被 NTP 覆盖,格式依赖 ⭐⭐⭐
os.system + date sudo date -s ... 代码最简单 安全风险高,功能弱 ⭐ (不推荐)

最终建议:

  1. 优先使用 subprocess 模块,因为它比 os.system 更安全、更强大。
  2. 优先使用 timedatectl 命令,尤其是在现代 Linux 发行版上,它是管理时间的标准方式。
  3. 始终记得使用 sudo 来运行你的 Python 脚本。
  4. 如果你的系统时间由 NTP 管理,在修改时间前先停止 NTP 服务,以防止你的设置被立即覆盖。
分享:
扫描分享到社交APP
上一篇
下一篇