当前位置: 首页 > news >正文

国民技术N32G430开发笔记(15)- IAP升级 树莓派串口发送数据

IAP升级 树莓派串口发送数据

1、树莓派接入usb转串口模块后,会生成/dev/ttyUSB0节点,因为树莓派内核已经编译usb_serial以及各模块的驱动。
我们直接对ttyUSB0节点编程即可。
2、协议同上一节
cmd + data_lenght + data0 + …+ datax + checksum
1、获取版本号 0x01 0x02 0x00 0x00 checksum
2、升级
1、进入升级模式 0x02 0x02 0x00 0x00 checksum
2、升级文件大小 0x03 0x04 0x00 0x00 0x00 0x00 checksum
3、数据包发送 0x04 0x80 0x00 0x00 0x00 0x00 … checksum
4、数据包发送完成 0x05 0x02 0x00 0x00 checksum

checksum采用crc16的检验方法。

3、升级过程:
1、发送升级模式命令。
2、发送文件大小命令
3、循环发送Application.bin的升级包,每包数据head+64个数据+checksum。
4、发送升级完成命令。
4、代码解析如下:
在这里插入图片描述
在build目录执行 cmake …;make 即可编译出uartiap。

CMakeLists.txt

cmake_minimum_required(VERSION 3.18.4)
project (uartIap)aux_source_directory(. C_SOURCES)
aux_source_directory(./UartIap C_SOURCES_UART)include_directories(./UartIap)add_executable(${PROJECT_NAME} ${C_SOURCES} ${C_SOURCES_UART})
target_link_libraries(${PROJECT_NAME} pthread)

n32g430_iap.c

#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include "uart.h"#define APPLICATION_PATH                "Application.bin"
#define UPGRADE_DATA_PACKAGES_LENGHT    0x40
#define UPGRADE_PACKAGES_LENGHT         0x40 + 0x04typedef enum{MI_FALSE  =   0,MI_TRUE   =   1,}MI_BOOL;typedef unsigned char   MI_U8;
typedef unsigned short  MI_U16;MI_U8 get_ver_cmd[6]            = {0x01,0x02,0x00,0x00,0x00,0x00};
MI_U8 update_cmd[6]             = {0x02,0x02,0x00,0x00,0x00,0x00};
MI_U8 file_size_cmd[8]          = {0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00};
MI_U8 file_package[UPGRADE_PACKAGES_LENGHT]         = {0x04,UPGRADE_DATA_PACKAGES_LENGHT};
MI_U8 update_complete_cmd[6]    = {0x05,0x02,0x00,0x00};
MI_U16 w_num = 0;static MI_U8 isRunning = 0;
char r_data[256] = {0};
sem_t sem;static MI_BOOL get_update_file_size(char * file_path,size_t *size)
{FILE *file;file = fopen(file_path,"rb");if (!file){perror("get_update_file_size fopen error\n");return MI_FALSE;}fseek(file, 0L, SEEK_END);*size = ftell(file);fclose(file);return MI_TRUE;
}static MI_U16 CRC16(MI_U8 * buf, MI_U16 len)
{MI_U16 i;MI_U16 crc = 0xffff;if (len == 0) {len = 1;}while (len--) {crc ^= *buf;for (i = 0; i<8; i++) {            if (crc & 1) {               crc >>= 1;        crc ^= 0xA001;            }      else {               crc >>= 1;            }       }     buf++;}return(crc);
}static MI_BOOL compare(MI_U8 *des,MI_U8 *src,int len)
{while (len--){if (*des != *src){return MI_FALSE;}des++;src++;}return MI_TRUE;
}static void send_get_version_cmd(int fd)
{int len = sizeof(get_ver_cmd);int crc = CRC16(get_ver_cmd,len-2);get_ver_cmd[len-2] = crc & 0x00ff;get_ver_cmd[len-1] = ((crc >> 8) & 0x00ff);serialWrite(fd,get_ver_cmd,sizeof(get_ver_cmd));
}static void send_enter_update_cmd(int fd)
{int len = sizeof(update_cmd);int crc = CRC16(update_cmd,len-2);update_cmd[len-2] = crc & 0x00ff;update_cmd[len-1] = ((crc >> 8) & 0x00ff);serialWrite(fd,update_cmd,sizeof(update_cmd));
}static MI_BOOL send_update_file_size_cmd(int fd)
{int len = sizeof(file_size_cmd);size_t file_size = 0;get_update_file_size(APPLICATION_PATH,&file_size);file_size_cmd[2] = (file_size >> 24 & (0xff));file_size_cmd[3] = (file_size >> 16 & (0xff));file_size_cmd[4] = (file_size >> 8 & (0xff));file_size_cmd[5] = (file_size & (0xff));int crc = CRC16(file_size_cmd,len-2);file_size_cmd[len-2] = crc & 0x00ff;file_size_cmd[len-1] = ((crc >> 8) & 0x00ff);serialWrite(fd,file_size_cmd,sizeof(file_size_cmd));return MI_TRUE;
}static MI_BOOL send_file_every_package(int fd)
{int len = sizeof(file_package);FILE *fp;size_t file_size;int package_num;MI_U8 package_buff[UPGRADE_DATA_PACKAGES_LENGHT] = {0};fp = fopen(APPLICATION_PATH,"rb");if (!fp){perror("fopen error\n");return MI_FALSE;}get_update_file_size(APPLICATION_PATH,&file_size);if (file_size % UPGRADE_DATA_PACKAGES_LENGHT == 0 ){package_num = file_size / UPGRADE_DATA_PACKAGES_LENGHT;}else{package_num = (file_size / UPGRADE_DATA_PACKAGES_LENGHT) + 1;}printf("pageage_num == %d\n",package_num);while (!feof(fp)/* condition */){/* code */int r_len = fread(package_buff,1,UPGRADE_DATA_PACKAGES_LENGHT,fp);// 最后读出来不满128 ,用0xff补全。if (r_len != UPGRADE_DATA_PACKAGES_LENGHT){for (int i=r_len;i<UPGRADE_DATA_PACKAGES_LENGHT;i++){package_buff[i] = 0xff;}}memcpy(&file_package[2],package_buff,sizeof(package_buff));int crc = CRC16(file_package,sizeof(file_package)-2);file_package[sizeof(file_package)-2] = crc & 0x00ff;file_package[sizeof(file_package)-1] = ((crc >> 8) & 0x00ff);usleep(30 * 1000);w_num++;printf("send package process == [%03d]\n", ((w_num * 100)/package_num));#if DEBUGfor(int i=0;i< len;i++){printf("0x%02x  ",file_package[i]);if ((i+1) % 16 == 0)printf("\n");}printf("\n");#endifmemset(r_data,0,sizeof(r_data));serialWrite(fd,file_package,len);sem_wait(&sem);
#if DEBUG// for(int i=0;i< len;i++)// {//     printf("0x%02x  ",r_data[i]);//     if ((i+1) % 16 == 0)//         printf("\n");// }// printf("\n");// int status = compare(r_data,file_package,20);// if (status)// {//     printf("send_file_every_package and receive cmd success!\n");// }// else// {//     perror("send_file_every_package not equal receive cmd\n");// }//printf("read len == %d  w_num == %d \n",len,w_num);#endif        }fclose(fp);return MI_TRUE;
}static MI_BOOL send_update_complete_cmd(int fd)
{int len = sizeof(update_complete_cmd);int crc = CRC16(update_complete_cmd,len-2);update_complete_cmd[len-2] = crc & 0x00ff;update_complete_cmd[len-1] = ((crc >> 8) & 0x00ff);serialWrite(fd,update_complete_cmd,sizeof(update_complete_cmd));return MI_TRUE;
}void *uart_read_thread(void *arg)
{int fd = *((int *)arg);size_t  size ;        sem_wait(&sem);while(isRunning){size = serialRead(fd,r_data,256); //阻塞方式去读#if DEBUG    if (size > 0){for(int i=0;i<size;i++){printf("0x%02x  ",r_data[i]);}printf("\n");}#endif    sem_post(&sem);}printf("uart_read_thread exit\n");pthread_exit(0);
}int main(int argc,char *argv[])
{int fd = 0;int ret;char w_data[] = "hello world\n";MI_U16 crc = 0;MI_BOOL status;pthread_t m_read_thread ;size_t update_file_size;sem_init(&sem, 0, 0);fd = serialOpen("/dev/ttyUSB0",115200);if (fd > 0){printf("open ttyUSB0 ok\n");}else{printf("open ttyUSB0 fail\n");return -1;}ret = pthread_create(&m_read_thread,NULL,uart_read_thread,&fd);if (ret){perror("pthread_create error\n");return -1;}else{isRunning = 1;sem_post(&sem);}sleep(1);// 获取一下N32G430C8L7的版本号memset(r_data,0,sizeof(r_data));send_get_version_cmd(fd);sem_wait(&sem);printf("get version == %s\n",r_data);memset(r_data,0,sizeof(r_data));send_enter_update_cmd(fd);sem_wait(&sem);status = compare(r_data,update_cmd,sizeof(update_cmd));if (status){printf("send_enter_update_cmd and receive cmd success!\n");}else{perror("send_enter_update_cmd not equal receive cmd\n");}get_update_file_size(APPLICATION_PATH,&update_file_size);printf("get update file size == %ld\n",update_file_size);memset(r_data,0,sizeof(r_data));send_update_file_size_cmd(fd);sem_wait(&sem);status = compare(r_data,file_size_cmd,sizeof(file_size_cmd));if (status){printf("send_update_file_size_cmd and receive cmd success!\n");}else{perror("send_update_file_size_cmd not equal receive cmd\n");}send_file_every_package(fd);memset(r_data,0,sizeof(r_data));send_update_complete_cmd(fd);sem_wait(&sem);pthread_cancel(m_read_thread);isRunning = 0;pthread_join(m_read_thread,NULL);serialClose(fd);printf("raspberryPi App exit!\n");
}

uart.c

#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include "uart.h"static speed_t getBaudRate(int baudRate)
{switch(baudRate) {case 0: return B0;case 50: return B50;case 75: return B75;case 110: return B110;case 134: return B134;case 150: return B150;case 200: return B200;case 300: return B300;case 600: return B600;case 1200: return B1200;case 1800: return B1800;case 2400: return B2400;case 4800: return B4800;case 9600: return B9600;case 19200: return B19200;case 38400: return B38400;case 57600: return B57600;case 115200: return B115200;case 230400: return B230400;case 460800: return B460800;case 500000: return B500000;case 576000: return B576000;case 921600: return B921600;case 1000000: return B1000000;case 1152000: return B1152000;case 1500000: return B1500000;case 2000000: return B2000000;case 2500000: return B2500000;case 3000000: return B3000000;case 3500000: return B3500000;case 4000000: return B4000000;default: return -1;}
}static int setParity(int fd,int dataBits,int stopBits,int parity)
{struct termios options;if (tcgetattr (fd, &options) != 0) {printf ("SetupSerial 1");return (-1);}options.c_cflag &= ~CSIZE;switch (dataBits) {case 7:options.c_cflag |= CS7;break;case 8:options.c_cflag |= CS8;break;default:fprintf (stderr, "Unsupported data size\n");return (-1);}switch (parity) {case 'n':case 'N':options.c_cflag &= ~PARENB; /* Clear parity enable */options.c_iflag &= ~INPCK;  /* Enable parity checking */break;case 'o':case 'O':options.c_cflag |= (PARODD | PARENB);options.c_iflag |= INPCK;   /* Disable parity checking */break;case 'e':case 'E':options.c_cflag |= PARENB;  /* Enable parity */options.c_cflag &= ~PARODD;options.c_iflag |= INPCK;   /* Disable parity checking */break;case 'S':case 's':           /*as no parity */options.c_cflag &= ~PARENB;options.c_cflag &= ~CSTOPB;break;default:fprintf (stderr, "Unsupported parity\n");return (-1);}switch (stopBits) {case 1:options.c_cflag &= ~CSTOPB;break;case 2:options.c_cflag |= CSTOPB;break;default:fprintf (stderr, "Unsupported stop bits\n");return (-1);}/* Set input parity option */if (parity != 'n')options.c_iflag |= INPCK;tcflush (fd, TCIFLUSH);options.c_cc[VTIME] = 0x01;options.c_cc[VMIN] =  0xFF; /* Update the options and do it NOW *///qd to set raw mode, which is copied from weboptions.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP| INLCR | IGNCR | ICRNL | IXON);options.c_oflag &= ~OPOST;options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);options.c_cflag &= ~(CSIZE | PARENB);options.c_cflag |= CS8;if (tcsetattr (fd, TCSANOW, &options) != 0) {perror ("SetupSerial 3");return (-1);}return 0;
}int serialOpen(const char *path, int baudRate)
{int fd;speed_t speed;/* Check arguments */{speed = getBaudRate(baudRate);if (speed == -1) {printf("get Baud rate error\n");return -1;}}{fd = open(path, O_RDWR);if (fd == -1){printf("open serial error =%d\n",fd);return -1;}}/* Configure device */{struct termios cfg;if (tcgetattr(fd, &cfg)){printf("tcgetattr() failed\n");close(fd);return -1;}cfmakeraw(&cfg);cfsetispeed(&cfg, speed);cfsetospeed(&cfg, speed);if (tcsetattr(fd, TCSANOW, &cfg)){printf("tcsetattr() failed\n");close(fd);return -1;}}setParity(fd,8,1,'N');//printf("open Success==%d\n",fd);return fd;
}int serialWrite(int fd,char *writeData,int len)
{if (fd > 0){write(fd,writeData,len);}else{printf("[File]=%s[Function]=%s error\n",__FILE__,__FUNCTION__);return -1;}return 0;
}int serialRead(int fd,char *readData,int len)
{size_t size = 0;if (fd > 0){size = read(fd,readData,len);}else{printf("[File]=%s[Function]=%s error\n",__FILE__,__FUNCTION__);return -1;}return size;
}int serialClose(int fd)
{close(fd);return 0;
}

uart.h

#ifndef __UART_H__
#define __UART_H__int serialOpen(const char *path, int baudRate);
int serialWrite(int fd,char *writeData,int len);
int serialRead(int fd,char *readData,int len);
int serialClose(int fd);#endif

5、视频

屏幕录制2023-05-03 15.39.07

6、代码路径 : https://gitee.com/xiaoguo-tec_0/raspberrypi

相关文章:

国民技术N32G430开发笔记(15)- IAP升级 树莓派串口发送数据

IAP升级 树莓派串口发送数据 1、树莓派接入usb转串口模块后&#xff0c;会生成/dev/ttyUSB0节点&#xff0c;因为树莓派内核已经编译usb_serial以及各模块的驱动。 我们直接对ttyUSB0节点编程即可。 2、协议同上一节 cmd data_lenght data0 … datax checksum 1、获取版本…...

svo论文解读

SVO: Semi-Direct Visual Odometry for Monocular and Multi-Camera Systems 2016TRO MOTION ESTIMATION 1 Sparse Image Alignment 从上一帧的特征投影到当前帧&#xff0c;最小化重投影误差计算帧间位姿&#xff08;patch44&#xff09; 2 Relaxation Through Feature Alig…...

DolphinScheduler海豚调度教程

DolphinScheduler 教程 &#xff08;一&#xff09;入门指南 简介 关于Dolphin Apache DolphinScheduler是一个分布式易扩展的可视化DAG工作流任务调度开源系统。解决数据研发ETL 错综复杂的依赖关系&#xff0c;不能直观监控任务健康状态等问题。DolphinScheduler以DAG流式…...

ubuntu脚本解释器踩坑:#!/bin/bash 与 #!/bin/sh

前言&#xff1a; 博主正在写linux的脚本的时候遇到&#xff1a;xx.sh: 3: Syntax error: "(" unexpected 查看shell脚本语法没有问题&#xff0c;后面发现是解释器的原因。 一、不同的解释器 #!是特殊的表示符&#xff0c;其后面根的是此解释此脚本的shell的路径…...

小松鼠踩一踩游戏

文章目录 一、 介绍和知识点九、UnityFacade 门面设计模式二、 声音全局管理器测试音频代码UI全局管理器父类抽象类 BaseManager子类 UIManager 四、 UI按钮的引用父类 BasePanel子类主面板 MainPanel子类 游戏中 GamePanel子类 游戏结果 ResultPanel 角色动画器、控制角色移动…...

使用crontab命令同步时间

crontab命令可以用于在Linux系统中定期同步时间。常用的时间同步方法有: 1. 使用ntpdate同步时间 可以添加如下crontab任务: */5 * * * * /usr/sbin/ntpdate time.nist.gov http://xn–5time-rg2hnkqin4vhsb6x8meq6d7yxa.nist.gov/ NTP服务器同步一次时间。 2. 使用ntpd作为…...

TortoiseGit提示No supported authentication methods available异常

TortoiseGit他属于git的客户端&#xff0c;可有可无&#xff0c;说白了就是将git命令给我们整理成了可直接操作的按钮。 本地代码是使用了SSH的方式去拉取的代码&#xff0c;但是通过TortoiseGit pull代码的时候发生了如下异常&#xff0c;而GitBash却可以正常使用。 TortoiseG…...

基于哈希表的用户管理系统

三大模块&#xff1a; - 哈希表模块 哈希函数 哈希表创建 哈希表销毁 - 用户管理模块 显示 增 删 改 查 - 文件模块 从文件导入用户信息 将用户信息导出至文件 1.哈希函数 //hash函数&#xff08;质数除余法&#xff09; int Hash_Fun1(data_type key){int pos key%P;…...

GO数组切片-线性数据结构

数据结构 类型 什么是类型 &#xff1f; 内存中的二进制数据本身没有什么区别&#xff0c;就是一串0或1的组合。 内存中有一个字节内容是0x63&#xff0c;他究竟是深恶 字符串?字符&#xff1f;还是整数&#xff1f; 本来0x63表示数字 但是文字必须编码成为0和1的组合 才能记…...

C++ STL学习之【优先级队列】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 16.11.17 文章目录 &#x1f307;前言&#x1f3d9;️正文1、优先级队列的使用1.1、基本功能1.2、优先级模式切换1.3、相关题目 2、模拟…...

keepalived脑裂现象

Keepealived最常见的问题是会出现脑裂现象&#xff1a; Master一直发送心跳消息给backup主机&#xff0c;如果中间的链路突然断掉&#xff0c;backup主机将无法收到master主机发送过来的心跳消息&#xff08;也就是vrrp报文&#xff09;&#xff0c;backup这时候会立即抢占mas…...

[stable-diffusion-art] 指北-1

https://stable-diffusion-art.com/beginners-guide/https://stable-diffusion-art.com/beginners-guide/ Stable Diffusion教程目录 - 知乎按&#xff1a; 这个外国教程站中的文章太好了&#xff0c;数量适当&#xff0c;质量很高可惜博文只能按时间浏览&#xff0c;所以整理…...

「C/C++」C/C++预处理器

博客主页&#xff1a;何曾参静谧的博客 文章专栏&#xff1a;「C/C」C/C学习 目录 一、宏替换 #define1. 定义常量2. 定义函数3. 定义代码块 二、条件编译 #if1. 使用 #ifdef、 #else 和 #endif2. 使用 #if 、#elif、#else和 #endif 编译不同版本的代码3. 使用 #ifndef 和 #def…...

java语言入门教程文章

好的&#xff0c;以下是Java语言入门教程&#xff1a; Java是一种高级编程语言&#xff0c;由Sun Microsystems于1995年推出。Java语言具有良好的可移植性和安全性&#xff0c;因此被广泛应用于Web应用程序、移动应用程序、企业应用程序等各个领域。本教程将带领初学者快速入门…...

基于灰狼算法的极限学习机(ELM)回归预测-附代码

基于灰狼算法的极限学习机(ELM)回归预测 文章目录 基于灰狼算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于灰狼算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用灰狼算法对极限学习机进行优化&#xff0c;并…...

【五一创作】ERP实施-委外业务-委外采购业务

委外业务主要有两种业务形态&#xff1a;委外采购和工序外协&#xff0c;委外采购主要是在MM模块中实现&#xff0c;工序外协主要由PP模块实现&#xff0c;工序外协中的采购订单创建和采购收货由MM模块实现。 委外采购概念 委外采购&#xff0c;有些企业也称为带料委外或者分包…...

DAY 54 数据库基础

数据库的基本概念 数据&#xff08;Data&#xff09;&#xff1a; 描述事务的符号记录包括数字、文字、图形、图像、声音、档案记录以”记录“形式按统一的格式进行存储 表&#xff1a; 将不同的记录组织在一起用来存储具体数据 数据库&#xff1a; 表的集合&#xff0c;…...

网络编程 总结二

一、TCP TCP模型 1. TCP搭建相关函数&#xff1a; 套接字Socket 1&#xff09;Socket函数&#xff1a; 2&#xff09;bind 3&#xff09;listen 4&#xff09;accept 5&#xff09;recv 注意&#xff1a; 1> TCP中的recv 可以替换成read&#xff1b; 2>TCP中的…...

消息称苹果Type-C口充电未设MFi限制,iOS17将更新Find My服务

根据国外科技媒体 iMore 报道&#xff0c;基于消息源 analyst941 透露的信息&#xff0c;苹果公司目前并未开发 MFi 限制。 根据推文信息内容&#xff0c;两款 iPhone 15 机型的最高充电功率为 20W&#xff0c;而 iPhone 15 Pro 机型的最高支持 27W 充电。 此前古尔曼表示苹…...

设计模式——工厂模式(简单工厂、工厂方法、抽象工厂)

是什么&#xff1f; 工厂模式的目的是将创建对象的具体过程隐藏起来&#xff0c;从而达到更高的灵活性 工厂模式分为&#xff1a;简单工厂模式、工厂方法模式、抽象工厂模式&#xff1b; 为什么&#xff1f; 在Java中&#xff0c;万物皆是对象&#xff0c;我们在使用的时候…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...