You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

69 lines
2.0 KiB

  1. package com.qyft.ms.app.service;
  2. import lombok.RequiredArgsConstructor;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.stereotype.Service;
  5. import java.io.IOException;
  6. import java.time.Instant;
  7. /**
  8. * 系统相关
  9. */
  10. @Slf4j
  11. @Service
  12. @RequiredArgsConstructor
  13. public class SystemService {
  14. /**
  15. * 获取当前时间戳毫秒
  16. */
  17. public long getCurrentEpochMilli() {
  18. return Instant.now().toEpochMilli();
  19. }
  20. /**
  21. * 将系统时区可选和系统时间必选一起设定
  22. *
  23. * @param epochMilli UTC 毫秒时间戳
  24. * @param zone 可选 IANA 时区 ID若为 null 或空则不修改时区
  25. */
  26. public void setSystemTime(long epochMilli, String zone) {
  27. // 1) 确定要设置的时区:客户端没传就用“Asia/Shanghai”
  28. String effectiveZone = (zone != null && !zone.isBlank())
  29. ? zone
  30. : "Asia/Shanghai";
  31. // 2) 先修改系统时区(总是执行)
  32. runCommand("timedatectl", "set-timezone", effectiveZone);
  33. // 3) 再用 date -s @<秒数> 方式设置系统时间
  34. long epochSecond = epochMilli / 1_000;
  35. runCommand("date", "-s", "@" + epochSecond);
  36. // 4) 将系统时钟写入到硬件时钟(RTC)
  37. runCommand("hwclock", "--systohc");
  38. }
  39. /**
  40. * 辅助执行系统命令并检查退出码
  41. */
  42. private void runCommand(String... cmd) {
  43. try {
  44. ProcessBuilder pb = new ProcessBuilder(cmd);
  45. pb.inheritIO();
  46. Process p = pb.start();
  47. int exit = p.waitFor();
  48. if (exit != 0) {
  49. throw new IllegalStateException(
  50. String.format("命令 %s 执行失败,退出码=%d", String.join(" ", cmd), exit)
  51. );
  52. }
  53. } catch (IOException | InterruptedException e) {
  54. Thread.currentThread().interrupt();
  55. throw new RuntimeException("执行系统命令失败: " + String.join(" ", cmd), e);
  56. }
  57. }
  58. }