【Golang星辰图】 Go系统编程实战:利用Go-syslog、Go-procfs、Go-udev等库实现系统管理和监控

Go系统编程实战:从Go-syslog到Go-apparmor,掌握系统管理和监控技能

前言:

在Linux系统中,系统编程是指利用操作系统提供的接口和库,进行系统级别的编程。Go语言作为一种静态编译、垃圾回收、并发编程的现代编程语言,在系统编程方面也有着广泛的应用。本文将介绍几个常用的Go系统编程库,包括Go-syslog、Go-procfs、Go-udev等,并通过实例代码介绍如何使用这些库实现系统管理和监控。

欢迎订阅专栏:Golang星辰图

文章目录

  • Go系统编程实战:从Go-syslog到Go-apparmor,掌握系统管理和监控技能
    • 前言:
    • 1. Go-syslog: 系统日志的库
      • 1.1 简介
      • 1.2 特点
      • 1.3 使用方法
      • 1.4 示例
    • 2. Go-procfs: 用于访问proc文件系统的库
      • 2.1 简介
      • 2.2 特点
      • 2.3 使用方法
      • 2.4 示例
    • 3. Go-udev: 用于访问udev设备的库
      • 3.1 简介
      • 3.2 特点
      • 3.3 使用方法
      • 3.4 示例
    • 4. Go-netlink: 用于访问Netlink协议的库
      • 4.1 简介
      • 4.2 特点
      • 4.3 使用方法
      • 4.4 示例
    • 5. Go-inotify: 用于访问inotify接口的库
      • 5.1 简介
      • 5.2 特点
      • 5.3 使用方法
      • 5.4 示例
    • 6. Go-cap: 用于访问Linux能力的库
      • 6.1 简介
      • 6.2 特点
      • 6.3 使用方法
      • 6.4 示例
    • 7. Go-seccomp: 用于访问seccomp接口的库
      • 7.1 简介
      • 7.2 特点
      • 7.3 使用方法
      • 7.4 示例
    • 8. Go-apparmor: 用于访问AppArmor接口的库
      • 8.1 简介
      • 8.2 特点
      • 8.3 使用方法
      • 8.4 示例
    • 总结:

1. Go-syslog: 系统日志的库

1.1 简介

Go-syslog是一个用于系统日志的Go库,它提供了一个简单的接口来发送和接收系统日志消息。

1.2 特点

  • 支持多种日志传输协议,如Syslog、UDP、TCP等
  • 支持日志消息的格式化和过滤
  • 支持日志消息的持久化存储

1.3 使用方法

以下是一个使用Go-syslog发送日志消息的示例:

package mainimport ("log""github.com/inconshreveable/log15""github.com/inconshreveable/log15/syslog"
)func main() {// 创建一个Syslog Hookhook, err := syslog.NewHook(syslog.Logfmt(), &syslog.WriterConfig{Network: "udp",Address: "localhost:514",Appname: "myapp",})if err != nil {log.Fatal(err)}// 创建一个Loggerlogger := log15.New("module", "main")logger.SetHandler(log15.LvlFilterHandler(log15.LvlInfo, hook))// 发送日志消息logger.Info("this is an info message")logger.Warn("this is a warn message")logger.Error("this is an error message")
}

1.4 示例

以下是一个使用Go-syslog接收日志消息的示例:

package mainimport ("log""github.com/inconshreveable/log15""github.com/inconshreveable/log15/syslog"
)func main() {// 创建一个Syslog Handlerhandler, err := syslog.NewHandler(syslog.Logfmt(), &syslog.ReaderConfig{Network: "udp",Address: "localhost:514",})if err != nil {log.Fatal(err)}// 创建一个Loggerlogger := log15.New()logger.SetHandler(handler)// 接收日志消息for {record, err := logger.Next()if err != nil {log.Fatal(err)}log.Printf("%+v\n", record)}
}

2. Go-procfs: 用于访问proc文件系统的库

2.1 简介

Go-procfs是一个用于访问proc文件系统的Go库,它提供了一个简单的接口来获取进程信息。

2.2 特点

  • 支持获取进程的基本信息,如进程ID、进程名、进程状态等
  • 支持获取进程的内存使用情况、CPU使用情况等性能指标
  • 支持获取进程的文件描述符、网络连接等资源使用情况

2.3 使用方法

以下是一个使用Go-procfs获取进程信息的示例:

package mainimport ("fmt""github.com/c9s/goprocinfo/linux"
)func main() {// 获取进程信息proc, err := linux.NewProc("")if err != nil {log.Fatal(err)}// 获取进程的基本信息fmt.Println("PID:", proc.Pid)fmt.Println("Name:", proc.Comm)fmt.Println("State:", proc.State)// 获取进程的内存使用情况mem, err := proc.Mem()if err != nil {log.Fatal(err)}fmt.Println("RSS:", mem.RSS)fmt.Println("VmSize:", mem.VmSize)// 获取进程的CPU使用情况cpu, err := proc.CPU()if err != nil {log.Fatal(err)}fmt.Println("User:", cpu.User)fmt.Println("System:", cpu.System)
}

2.4 示例

以下是一个使用Go-procfs获取进程资源使用情况的示例:

package mainimport ("fmt""github.com/c9s/goprocinfo/linux"
)func main() {// 获取进程信息proc, err := linux.NewProc("")if err != nil {log.Fatal(err)}// 获取进程的文件描述符信息fds, err := proc.FDs()if err != nil {log.Fatal(err)}for _, fd := range fds {fmt.Println("FD:", fd.FD)fmt.Println("Path:", fd.Path)}// 获取进程的网络连接信息conn, err := proc.NetConnections()if err != nil {log.Fatal(err)}for _, c := range conn {fmt.Println("Local Address:", c.LocalAddr)fmt.Println("Remote Address:", c.RemoteAddr)}
}

3. Go-udev: 用于访问udev设备的库

3.1 简介

Go-udev是一个用于访问udev设备的Go库,它提供了一个简单的接口来获取设备信息。

3.2 特点

  • 支持获取设备的基本信息,如设备名、设备类型、设备编号等
  • 支持获取设备的属性信息,如设备序列号、设备厂商等
  • 支持监听设备事件,如设备添加、删除、更改等

3.3 使用方法

以下是一个使用Go-udev获取设备信息的示例:

package mainimport ("fmt""github.com/godbus/dbus/v5""github.com/vpavlin/udev/libudev"
)func main() {// 创建一个Udev对象udev, err := libudev.NewUdev()if err != nil {log.Fatal(err)
}// 获取设备信息dev, err := udev.DeviceNewFromSysPath("/sys/class/block/sda")if err != nil {log.Fatal(err)}// 获取设备的基本信息fmt.Println("Name:", dev.GetName())fmt.Println("Type:", dev.GetDevtype())fmt.Println("Number:", dev.GetDevnum())// 获取设备的属性信息fmt.Println("Serial:", dev.GetPropertyValue("ID_SERIAL"))fmt.Println("Vendor:", dev.GetPropertyValue("ID_VENDOR"))
}

3.4 示例

以下是一个使用Go-udev监听设备事件的示例:

package mainimport ("fmt""github.com/godbus/dbus/v5""github.com/vpavlin/udev/libudev"
)func main() {// 创建一个Udev对象udev, err := libudev.NewUdev()if err != nil {log.Fatal(err)}// 创建一个Monitor对象mon, err := udev.MonitorNewFromNetlink("udev")if err != nil {log.Fatal(err)}// 监听设备事件for {dev, err := mon.ReceiveDevice()if err != nil {log.Fatal(err)}fmt.Println("Action:", dev.GetAction())fmt.Println("Name:", dev.GetName())fmt.Println("Type:", dev.GetDevtype())fmt.Println("Number:", dev.GetDevnum())}
}

4. Go-netlink: 用于访问Netlink协议的库

4.1 简介

Go-netlink是一个用于访问Netlink协议的Go库,它提供了一个简单的接口来发送和接收Netlink消息。

4.2 特点

  • 支持多种Netlink协议,如RTNetlink、Genetlink等
  • 支持发送和接收Netlink消息的格式化和过滤
  • 支持监听Netlink事件,如路由表更改、网络接口更改等

4.3 使用方法

以下是一个使用Go-netlink发送RTNetlink消息的示例:

package mainimport ("fmt""github.com/vishvananda/netlink"
)func main() {// 创建一个RTNetlink Handlehandle, err := netlink.NewHandle()if err != nil {log.Fatal(err)}// 创建一个RTNetlink消息msg := &netlink.Route{LinkIndex: 1,Dst:       &net.IPNet{IP: net.ParseIP("192.168.1.0"), Mask: net.CIDRMask(24, 32)},Gw:        net.ParseIP("192.168.1.1"),}// 发送RTNetlink消息err = handle.Add(msg)if err != nil {log.Fatal(err)}// 接收RTNetlink消息msg, err = handle.Get(msg)if err != nil {log.Fatal(err)}fmt.Println(msg)
}

4.4 示例

以下是一个使用Go-netlink监听RTNetlink事件的示例:

package mainimport ("fmt""github.com/vishvananda/netlink"
)func main() {// 创建一个RTNetlink Handlehandle, err := netlink.NewHandle()if err != nil {log.Fatal(err)}// 创建一个RTNetlink Link消息link := &netlink.Link{LinkAttrs: netlink.LinkAttrs{Name: "eth0",},}// 监听RTNetlink Link事件err = handle.Link.Listen(link)if err != nil {log.Fatal(err)}// 接收RTNetlink Link事件for {msg, err := handle.Link.Recv()if err != nil {log.Fatal(err)}fmt.Println(msg)}
}

5. Go-inotify: 用于访问inotify接口的库

5.1 简介

Go-inotify是一个用于访问inotify接口的Go库,它提供了一个简单的接口来监听文件系统事件。

5.2 特点

  • 支持监听文件系统中文件和目录的更改、创建、删除等事件
  • 支持过滤文件系统事件,以减少不必要的事件通知
  • 支持监听多个文件和目录,以及递归监听目录下的所有文件和子目录

5.3 使用方法

以下是一个使用Go-inotify监听文件系统事件的示例:

package mainimport ("fmt""github.com/fsnotify/fsnotify"
)func main() {// 创建一个Watcher对象watcher, err := fsnotify.NewWatcher()if err != nil {log.Fatal(err)}defer watcher.Close()// 监听文件系统事件done := make(chan bool)go func() {for {select {case event := <-watcher.Events:fmt.Println("event:", event)if event.Op&fsnotify.Write == fsnotify.Write {fmt.Println("modified file:", event.Name)}case err := <-watcher.Errors:fmt.Println("error:", err)}}}()// 添加监听目录err = watcher.Add("/path/to/dir")if err != nil {log.Fatal(err)}// 阻塞主线程,直到接收到退出信号<-done
}

5.4 示例

以下是一个使用Go-inotify递归监听目录下的所有文件和子目录的示例:

package mainimport ("fmt""github.com/fsnotify/fsnotify"
)
func main() {
// 创建一个Watcher对象
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()// 监听文件系统事件done := make(chan bool)go func() {for {select {case event := <-watcher.Events:fmt.Println("event:", event)if event.Op&fsnotify.Write == fsnotify.Write {fmt.Println("modified file:", event.Name)}case err := <-watcher.Errors:fmt.Println("error:", err)}}}()// 递归添加监听目录err = watchDir("/path/to/dir", watcher)if err != nil {log.Fatal(err)}// 阻塞主线程,直到接收到退出信号<-done
}func watchDir(path string, watcher *fsnotify.Watcher) error {// 添加监听目录err := watcher.Add(path)if err != nil {return err}// 读取目录下的所有文件和子目录files, err := ioutil.ReadDir(path)if err != nil {return err}// 递归添加监听子目录for _, file := range files {if file.IsDir() {err = watchDir(filepath.Join(path, file.Name()), watcher)if err != nil {return err}}}return nil
}

6. Go-cap: 用于访问Linux能力的库

6.1 简介

Go-cap是一个用于访问Linux能力的Go库,它提供了一个简单的接口来获取和设置进程的能力。

6.2 特点

  • 支持获取进程的能力集,包括有效能力、可执行能力、继承能力等
  • 支持设置进程的能力集,包括添加、删除、设置能力等
  • 支持检查进程是否具有指定的能力

6.3 使用方法

以下是一个使用Go-cap获取进程能力集的示例:

package mainimport ("fmt""github.com/bronze1man/go-cap/cap"
)func main() {// 获取进程的能力集caps, err := cap.GetCaps()if err != nil {log.Fatal(err)}// 打印进程的有效能力fmt.Println("Effective:", caps.Effective())// 打印进程的可执行能力fmt.Println("Permitted:", caps.Permitted())// 打印进程的继承能力fmt.Println("Inheritable:", caps.Inheritable())
}

6.4 示例

以下是一个使用Go-cap设置进程能力集的示例:

package mainimport ("fmt""github.com/bronze1man/go-cap/cap"
)func main() {// 获取进程的能力集caps, err := cap.GetCaps()if err != nil {log.Fatal(err)}// 添加CAP_NET_ADMIN能力err = caps.Add(cap.CAP_NET_ADMIN)if err != nil {log.Fatal(err)}// 设置进程的有效能力为CAP_NET_ADMINerr = caps.SetEffective(cap.CAP_NET_ADMIN)if err != nil {log.Fatal(err)}// 检查进程是否具有CAP_NET_ADMIN能力hasCap, err := caps.Has(cap.CAP_NET_ADMIN)if err != nil {log.Fatal(err)}fmt.Println("Has CAP_NET_ADMIN:", hasCap)
}

7. Go-seccomp: 用于访问seccomp接口的库

7.1 简介

Go-seccomp是一个用于访问seccomp接口的Go库,它提供了一个简单的接口来限制进程的系统调用。

7.2 特点

  • 支持创建和加载seccomp过滤器,以限制进程的系统调用
  • 支持添加、删除、修改过滤器规则,以实现精细化的系统调用控制
  • 支持检查进程是否被seccomp限制

7.3 使用方法

以下是一个使用Go-seccomp限制进程系统调用的示例:

package mainimport ("fmt""github.com/seccomp/libseccomp-golang/v3/seccomp"
)func main() {// 创建一个seccomp过滤器filter, err := seccomp.NewFilter()if err != nil {log.Fatal(err)}// 添加允许的系统调用err = filter.AllowSyscalls(seccomp.SyscallRead,seccomp.SyscallWrite,seccomp.SyscallExit,)if err != nil {log.Fatal(err)}// 默认拒绝其他系统调用err = filter.DefaultAction(seccomp.ActKill)if err != nil {log.Fatal(err)}// 加载seccomp过滤器err = filter.Load()if err != nil {log.Fatal(err)}// 检查进程是否被seccomp限制isLimited, err := filter.IsLimited()if err != nil {log.Fatal(err)}fmt.Println("Is seccomp limited:", isLimited)
}

7.4 示例

以下是一个使用Go-seccomp实现精细化的系统调用控制的示例:

package mainimport ("fmt""github.com/seccomp/libseccomp-golang/v3/seccomp"
)func main() {// 创建一个seccomp过滤器filter, err := seccomp.NewFilter()if err != nil {log.Fatal(err)}// 添加允许的系统调用err = filter.AllowSyscalls(seccomp.SyscallRead,seccomp.SyscallWrite,seccomp.SyscallExit,)if err != nil {log.Fatal(err)}// 添加限制的系统调用err = filter.AddRule(seccomp.NewRule(seccomp.ActionAllow,seccomp.SyscallOpen,seccomp.CompareEqual,0,seccomp.Arg1,"/path/to/file",))if err != nil {log.Fatal(err)}// 默认拒绝其他系统调用err = filter.DefaultAction(seccomp.ActKill)if err != nil {log.Fatal(err)}// 加载seccomp过滤器err = filter.Load()if err != nil {log.Fatal(err)}// 检查进程是否被seccomp限制isLimited, err := filter.IsLimited()if err != nil {log.Fatal(err)}fmt.Println("Is seccomp limited:", isLimited)
}

8. Go-apparmor: 用于访问AppArmor接口的库

8.1 简介

Go-apparmor是一个用于访问AppArmor接口的Go库,它提供了一个简单的接口来管理AppArmor安全策略。

8.2 特点

  • 支持加载、卸载、查询AppArmor安全策略
  • 支持添加、删除、修改安全策略规则,以实现精细化的访问控制
  • 支持检查进程是否被AppArmor限制

8.3 使用方法

以下是一个使用Go-apparmor加载AppArmor安全策略的示例:

package mainimport ("fmt""github.com/ubuntu/go-apparmor/apparmor"
)func main() {// 创建一个AppArmor对象aa, err := apparmor.New()if err != nil {log.Fatal(err)}// 加载AppArmor安全策略err = aa.LoadProfile("profile_name")if err != nil {log.Fatal(err)}// 检查进程是否被AppArmor限制isConfined, err := aa.IsConfined("profile_name")if err != nil {log.Fatal(err)}fmt.Println("Is AppArmor confined:", isConfined)
}

8.4 示例

以下是一个使用Go-apparmor实现精细化的访问控制的示例:

package mainimport ("fmt""github.com/ubuntu/go-apparmor/apparmor"
)func main() {// 创建一个AppArmor对象aa, err := apparmor.New()if err != nil {log.Fatal(err)}// 加载AppArmor安全策略err = aa.LoadProfile("profile_name")if err != nil {log.Fatal(err)}// 添加安全策略规则err = aa.AddRule("profile_name", "rule_text")if err != nil {log.Fatal(err)}// 删除安全策略规则err = aa.DeleteRule("profile_name", "rule_text")if err != nil {log.Fatal(err)}// 检查进程是否被AppArmor限制isConfined, err := aa.IsConfined("profile_name")if err != nil {log.Fatal(err)}fmt.Println("Is AppArmor confined:", isConfined)
}

总结:

本文通过介绍几个常用的Go系统编程库,并提供了详细的实例代码,帮助读者了解如何使用Go语言进行系统管理和监控。这些库提供了简单易用的接口,使得Go语言在系统编程方面具有强大的能力。通过学习本文,读者可以更好地利用Go语言进行系统编程,实现系统管理和监控。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/760401.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

复用与多址的联系与区别

开头请记住一句话&#xff1a;复用针对资源&#xff0c;多址针对用户。 一、复用 1、复用是指一个信道传输多个信号&#xff0c;以提高资源利用率&#xff0c;针对的是信道资源。相当于高速公路上的车道&#xff0c;车道越多&#xff0c;传输速率越快&#xff0c;资源利用率也越…

Linux——进程信号(二)

目录 1、阻塞信号 1.1、信号其他相关常见概念 1.2、在内核中的表示 1.3、sigset_t 1.4、信号集操作函数 2、捕捉信号 2.1、内核如何捕捉信号 5.2、sigaction 1、阻塞信号 1.1、信号其他相关常见概念 实际执行信号的处理动作被称为信号递达&#xff08;Delivery&#x…

sentinel黑白名单权限控制

黑白名单权限控制 规则配置 规则创建 创建一个 AuthorityRule 规则对象三个关键要素 setStrategy: 黑白名单类型setResource: 规则和资源的绑定关系setLimitApp: 限制的来源 调用 AuthorityRuleManager.loadRules()加载规则 监听器实例化和管理 AuthorityPropertyListener…

【Leetcode】top 100 链表

基础知识补充 单向链表结构&#xff1a;item存储数据 next指向下一结点地址 head保存首地址 class Node(object): # 创建结点def __init__(self, item): self.item item # item存放数据元素self.next None # next是下一个…

【教程】混淆代码保护与优化

在本文中&#xff0c;我们将介绍如何在iOS项目中利用混淆技术来保护源代码安全并实现优化。我们将分别针对Swift和OC项目&#xff0c;详细介绍如何使用脚本和工具进行代码混淆&#xff0c;并解决在混淆过程中可能遇到的问题。随着移动应用市场的不断扩大&#xff0c;iOS应用的安…

Mysql编译安装

首先准备两个包&#xff1a;mysql-5.7.17.tar.gz和boost_1_59_0.tar.gz yum -y install gcc gcc-c ncurses ncurses-devel bison cmake 然后创建程序用户管理 useradd -s /sbin/nologin mysql 接着解压包 tar zxvf mysql-5.7.17.tar.gz -C /opt tar zxvf boost_1_59_0.tar.…

美团一面3月20日

优选部门 1.面向对象编程是什么 2.面向对象特性&#xff0c;分别说说 3.Java里面有几种修饰符 4.不加修饰符和protect什么区别 5.接口和抽象类的区别 6.了解哪些设计模式 7.手写单例模式 8.写的synchronized什么作用&#xff0c;&#xff08;.class&#xff09;是什么意思&…

使用Pygame做一个乒乓球游戏

项目介绍 使用Pygame做一个乒乓球游戏。左侧为电脑&#xff0c;右侧为玩家。 视频地址-YT 视频搬运-B站 视频教程约90分钟。 代码地址 环境&#xff1a;需要pygame库&#xff0c;可用pip安装&#xff1a;pip install pygame 1. 基础版本 首先进行一些初始化&#xff0c;初始…

线性结构-线性表

线性结构-线性表 数据结构中的逻辑结构分为线性结构和非线性结构&#xff0c;线性结构是n个数据元素的有序&#xff08;次序&#xff09;集合&#xff0c;它有下列几个特征&#xff1a; 1&#xff0e;集合中必存在唯一的一个"第一个元素"&#xff1b; 2&#xff0…

java NIO群聊系统

demo要求&#xff1a; 1&#xff09;编写一个NIO群聊系统&#xff0c;实现服务器端和客户端之间的数据简单通讯&#xff08;非阻塞&#xff09; 2&#xff09;实现多人群聊 3&#xff09;服务器端&#xff1a;可以监测用户上线&#xff0c;离线&#xff0c;并实现消息转发功…

python 爬虫 地理空间DEM 制作中国地形

一.配置Python 爬虫 环境 from selenium import webdriver import time # from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import Byfrom selenium.webdriver.common.keys import Keys # from selenium.webdriver.comm…

Langchain-chatchat+ChatGlm3-6b部署

我的环境 升级了下配置&#xff0c;加载知识库成功 内存&#xff1a;16GB 32B 显卡&#xff1a;GTX1060-6G RTX4080 Laptop-12G 1. 基础环境准备 1.1. 安装anaconda&#xff0c;创建环境python版本3.11 conda create -n chatglm3 python3.11 conda activate chatglm3 1.…

如何在CentOS搭建docker compose ui可视化工具并无公网IP远程管理容器

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

蓝桥杯 2023 省A 更小的数

主要思路&#xff1a; 输入一个长度为n的字符串&#xff0c;用二维数组dp[i][j]来记录子串[i, j]是否需要反转一次才能满足条件。使用动态规划自底向上地填充dp数组。根据问题的要求&#xff0c;需要考虑字符串的子串中字符的大小关系来判断是否需要反转。最后统计满足条件的子…

静态扭矩,是用公称扭矩还是最小动态扭矩作为对比?——​suntorque智能扭矩系统​

在机械工程和动力学领域&#xff0c;扭矩是一个至关重要的概念。当我们讨论到扭矩时&#xff0c;常常会遇到静态扭矩和动态扭矩的说法。特别是在实际应用中&#xff0c;工程师们经常需要对比和选择使用哪种扭矩作为参考。那么&#xff0c;静态扭矩&#xff0c;是用公称扭矩还是…

【C/C++】详解 assert() 断言(什么是assert? assert有什么作用?)

目录 一、前言 二、什么是 assert ? 三、assert 的用法 四、assert 案例解析 五、assert 断言的使用原则 六、共勉 一、前言 在编写程序过程中&#xff0c;尤其是调试代码时&#xff0c;往往需要一个提醒代码漏洞/Bug的小助手&#xff0c;以便于程序员及时修改和完善代码…

LeetCode 回文排列 java题解

题目 字符总数奇数&#xff1a;最多一个字符出现奇数次 字符总数偶数&#xff1a;所有字符都出现偶数次 可以使用哈希表。存储次数后再遍历哈希表判断是否符合。为了避免遍历&#xff0c;两次遇到同样的字符&#xff0c;一次加一次减就可以消掉&#xff0c;出现偶数次的字符最终…

C语言例3-38:强制类型转换的例子

数据类型强制转换的一般格式 &#xff08;数据类型符&#xff09;&#xff08;表达式&#xff09; &#xff01;&#xff01;&#xff01;注&#xff1a;第一个括号不能省略&#xff1b;第二个括号内是单个常量或变量时可省略。 例3-38&#xff1a;强制类型转换的例子 (doub…

109 项目整合 spring-quartz 启动自动执行定时任务

前言 项目中使用了 quartz 来支持定时任务的相关基础支撑, 但是 最近添加了一个 资源消耗比较高的定时任务, 发布到测试环境之后, 发现服务突然 起不起来了[资源比较有限] 然后 查看了一下日志, 这个定时任务怎么在执行?, 不是 配置的是 凌晨两点么, 然后 仔细一看 几乎配置…

python课后习题一

题目&#xff1a; 1. 2. 解题过程&#xff1a; 1. """计算年数和天数""" minute int(input("请输入分钟数&#xff1a;")) hours minute // 60 days hours // 24 years days // 365 last_days days % 365 print(f"{minut…