前言

网易云的Vip音乐下载下来,格式不是mp3/flac这种通用的音乐格式,而是经过加密的ncm文件。只有用网易云的音乐App才能够打开。于是想到可不可以把.ncm文件转换成mp3或者flac文件,上google查了一下,发现有不少人已经做了这件事,但没有发现C语言版本的,就想着写一个纯C语言版本的ncm转mp3/flac。

NCM文件结构

ncm文件的结构,网上有人解析出来了,分为下面几个部分

信息 大小 说明
Magic Header 10 bytes 文件头
Key Length 4 bytes AES128加密后的RC4密钥长度,字节是按小端排序。
Key Data Key Length 用AES128加密后的RC4密钥。
1. 先按字节对0x64进行异或。
2. AES解密,去除填充部分。
3. 去除最前面'neteasecloudmusic'17个字节,得到RC4密钥。
Music Info Length 4 bytes 音乐相关信息的长度,小端排序。
Music Info Data Music Info Length Json格式音乐信息数据。
1. 按字节对0x63进行异或。
2. 去除最前面22个字节。
3. Base64进行解码。
4. AES解密。
6. 去除前面6个字节得到Json数据。
CRC 4 bytes 跳过
Gap 5 bytes 跳过
Image Size 4 bytes 图片的大小
Image Image Size 图片数据
Music Data - 1. RC4-KSA生成S盒。
2. 用S盒解密(自定义的解密方法),不是RC4-PRGA解密。

两个AES对应密钥

unsigned char meta_key[] = { 0x23,0x31,0x34,0x6C,0x6A,0x6B,0x5F,0x21,0x5C,0x5D,0x26,0x30,0x55,0x3C,0x27,0x28 };

unsigned char core_key[] = { 0x68,0x7A,0x48,0x52,0x41,0x6D,0x73,0x6F,0x35,0x6B,0x49,0x6E,0x62,0x61,0x78,0x57 };

不得不佩服当初破解这个东西的人,不仅把文件结构摸得请清楚楚,还把密钥也搞到手,应该是个破解大神。有了上面的东西,剩下的就很简单了,按部就班来就行了。

一些算法准备

开始前我们需要把AES算法,BASE64算法,RC4算法和Json解析算法先写好。

除此之外还有一个编码问题,解析出来的ncm文件是用utf-8编码存储的,所以它在中文windows系统下汉字会出现乱码,因为中文windows系统采用的编码是GBK,两者不兼容,所以我们要写一个编码转换算法,将utf8格式字符串转位GBK的。Linux下不用转换,Linux本身就是用UTF-8的。

C语言没有这些库,都要自己来。

  • AES用GitHub上的

    tiny-AES-c
  • JSON用GitHub上的CJSON

    CJSON
  • Base64和RC4算法比较简单我们自己写
unsigned char* base64_decode(unsigned char* code,int len,int * actLen)
{
//根据base64表,以字符找到对应的十进制数据
int table[] = { 0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,62,0,0,0,
63,52,53,54,55,56,57,58,
59,60,61,0,0,0,0,0,0,0,0,
1,2,3,4,5,6,7,8,9,10,11,12,
13,14,15,16,17,18,19,20,21,
22,23,24,25,0,0,0,0,0,0,26,
27,28,29,30,31,32,33,34,35,
36,37,38,39,40,41,42,43,44,
45,46,47,48,49,50,51
};
long str_len;
unsigned char* res;
int i, j; //计算解码后的字符串长度
//判断编码后的字符串后是否有=
if (strstr(code, "=="))
str_len = len / 4 * 3 - 2;
else if (strstr(code, "="))
str_len = len / 4 * 3 - 1;
else
str_len = len / 4 * 3; *actLen = str_len;
res = malloc(sizeof(unsigned char) * str_len + 1);
res[str_len] = '\0'; //以4个字符为一位进行解码
for (i = 0, j = 0; i < len - 2; j += 3, i += 4)
{
res[j] = ((unsigned char)table[code[i]]) << 2 | (((unsigned char)table[code[i + 1]]) >> 4);
res[j + 1] = (((unsigned char)table[code[i + 1]]) << 4) | (((unsigned char)table[code[i + 2]]) >> 2);
res[j + 2] = (((unsigned char)table[code[i + 2]]) << 6) | ((unsigned char)table[code[i + 3]]);
}
return res; }
  • RC4生成S盒
//用key生成S盒
/*
* s: s盒
* key: 密钥
* len: 密钥长度
*/
void rc4Init(unsigned char* s, const unsigned char* key, int len)
{
int i = 0, j = 0;
unsigned char T[256] = { 0 }; for (i = 0; i < 256; i++)
{
s[i] = i;
T[i] = key[i % len];
} for (i = 0; i < 256; i++)
{
j = (j + s[i] + T[i]) % 256;
unsigned tmp = s[i];
s[i]=s[j];
s[j]=tmp;
}
}
//针对NCM文件的解密
//异或关系
/*
* s: s盒
* data: 要加密或者解密的数据
* len: data的长度
*/
void rc4PRGA(unsigned char* s, unsigned char* data, int len)
{
int i = 0;
int j = 0;
int k = 0;
int idx = 0;
for (idx = 0; idx < len; idx++)
{
i = (idx + 1) % 256;
j = (i + s[i]) % 256;
k= (s[i] + s[j]) % 256;
data[idx]^=s[k]; //异或
}
}
  • Windows下utf8转GBK
#ifdef WIN32
#include<Windows.h>
//返回转换好的字符串指针
unsigned char* utf8ToGbk(unsigned char*src,int len)
{
wchar_t* tmp = (wchar_t*)malloc(sizeof(wchar_t) * len+2);
unsigned char* newSrc = (unsigned char*)malloc(sizeof(unsigned char) * len + 2); MultiByteToWideChar(CP_UTF8, 0, src, -1, tmp, len);
WideCharToMultiByte(CP_ACP, 0, tmp, -1, newSrc, len+2, NULL,NULL);
return newSrc;
}
#endif

NCM文件解析

按照NCM文件结构一步一步读取数据来进行解析

//fileName:要转换的文件
void readFileData(const char* fileName)
{
FILE* f;
f = fopen(fileName, "rb");
if (!f)
{
printf("No such file: %s\n", fileName);
return;
} unsigned char buf[16];
int len=0;
int i = 0; unsigned char meta_key[] = { 0x23,0x31,0x34,0x6C,0x6A,0x6B,0x5F,0x21,0x5C,0x5D,0x26,0x30,0x55,0x3C,0x27,0x28 };
unsigned char core_key[] = { 0x68,0x7A,0x48,0x52,0x41,0x6D,0x73,0x6F,0x35,0x6B,0x49,0x6E,0x62,0x61,0x78,0x57 }; fseek(f, 10, SEEK_CUR); //f从当前位置移动10个字节
fread(buf, 1, 4, f); //读取rc4 key 的长度 len = (buf[3] << 8 | buf[2]) << 16 | (buf[1] << 8 | buf[0]);
unsigned char* rc4Key= (unsigned char*)malloc(sizeof(unsigned char) * len);
fread(rc4Key, 1, len, f); //读取rc4数据 //解密rc4密钥
for (i = 0; i < len; i++)
{
rc4Key[i] ^= 0x64;
} struct AES_ctx ctx;
AES_init_ctx(&ctx, core_key); //使用core_key密钥
int packSize = len / 16; //采用的是AES-ECB加密方式,和Pkcs7padding填充
for (i = 0; i < packSize; i++)
{
AES_ECB_decrypt(&ctx, &rc4Key[i * 16]);
}
int pad = rc4Key[len - 1]; //获取填充的长度
rc4Key[len - pad] = '\0'; //去除填充的部分,得到RC4密钥 fread(buf, 1, 4, f); //读取Music Info 长度数据
len = ((buf[3] << 8 | buf[2]) << 16) | (buf[1] << 8 | buf[0]);
unsigned char* meta = (unsigned char*)malloc(sizeof(unsigned char) * len);
fread(meta, 1, len, f); //读取Music Info数据
//解析Music info信息
for (i = 0; i < len; i++)
{
meta[i] ^= 0x63;
}
int act = 0;
unsigned char* data = base64_decode(&meta[22], len - 22, &act); //base64解码
AES_init_ctx(&ctx, meta_key); //AES解密
packSize = act / 16;
for (i = 0; i < packSize; i++)
{
AES_ECB_decrypt(&ctx, &data[i * 16]);
}
pad = data[act - 1];
data[act - pad] = '\0'; //去除填充部分
unsigned char* newData = data;
#ifdef WIN32 newData = utf8ToGbk(data, strlen(data)); #endif cJSON* cjson = cJSON_Parse(&newData[6]); //json解析,获取格式和名字等
if (cjson == NULL)
{
printf("cjson parse failed\n");
return;
}
//printf("%s\n", cJSON_Print(cjson)); //输出json fseek(f, 9, SEEK_CUR); //从当前位置跳过9个字节
fread(buf, 1, 4, f); //读取图片大小
len = (buf[3] << 8 | buf[2]) << 16 | (buf[1] << 8 | buf[0]);
unsigned char* img = (unsigned char*)malloc(sizeof(unsigned char) * len);
fread(img, 1, len, f); //读取图片数据 int offset= 1024 * 1024 * 10; //10MB 音乐数据一般比较大一次读入10MB
int total = 0;
int reSize = offset;
unsigned char* musicData = (unsigned char*)malloc(offset); //10m while (!feof(f))
{
len = fread(musicData+total, 1, offset, f); //每次读取10M
total += len;
reSize += offset;
musicData=realloc(musicData,reSize); //扩容
} unsigned char sBox[256] = { 0 }; //s盒
rc4Init(sBox, &rc4Key[17], strlen(&rc4Key[17])); //用rC4密钥进行初始化s盒
rc4PRGA(sBox, musicData, total); //解密 //拼接文件名(artist + music name+format)
char* musicName = cJSON_GetObjectItem(cjson, "musicName")->valuestring;
cJSON* sub = cJSON_GetObjectItem(cjson, "artist");
char*artist=cJSON_GetArrayItem(cJSON_GetArrayItem(sub, 0),0)->valuestring;
char* format = cJSON_GetObjectItem(cjson, "format")->valuestring;
char* saveFileName =(char*)malloc(strlen(musicName) + strlen(artist) + strlen(format)+5);
sprintf(saveFileName, "%s - %s.%s", artist, musicName, format);
FILE* fo=fopen(saveFileName, "wb");
if (fo == NULL)
{
printf("The fileName - '%s' is invalid in this system\n", saveFileName);
}
else
{
fwrite(musicData, 1, total, fo);
fclose(fo);
} #ifdef WIN32
free(newData);
#endif
free(data);
free(meta);
free(img);
free(musicData);
fclose(f); }
  1. AES采用的是AES-ECB模式,pack7padding填充方式。即16个字节为一组,如果不够16个字节,那就缺几个字节就填充几个字节,每个字节的值都是缺少的字节数。所以获取最后一个字节的值就知道要填充了几个字节。
  2. RC4解密那里,不是按RC4的来的,虽说叫RC4,但只有生成S盒那里是一样的,其它的不是按RC4算法来的。
  3. 有些解析出来音乐的名字,系统是不支持的,比如带'/'的,在创建新文件写入时会失败。
  4. 以"結束バンド - ギターと孤独と蒼い惑星.ncm"为例看看它的json数据是怎么样的

{

"musicId": 1991012773,

"musicName": "ギターと孤独と蒼い惑星",

"artist": [["結束バンド", 54103171]],

"albumId": 153542094,

"album": "ギターと孤独と蒼い惑星",

"albumPicDocId": "109951167983448236",

"albumPic": "https://p4.music.126.net/rfstzrVK05hCPjU-4mzSFA==/109951167983448236.jpg",

"bitrate": 320000,

"mp3DocId": "f481d20151f01d5d681d2768d753ad64",

"duration": 229015,

"mvId": 0,

"alias": ["TV动画《孤独摇滚!》插曲"],

"transNames": [],

"format": "mp3",

"flag": 4

}

可以根据需要自由提取需要的信息

完整代码

点击查看代码
/*
* date:2022-12-12
* author: FL
* purpose: ncm file to mp3
*/ #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include "aes.h"
#include "cJSON.h" #ifdef WIN32
#include<Windows.h>
//返回转换好的字符串指针
unsigned char* utf8ToGbk(unsigned char*src,int len)
{
wchar_t* tmp = (wchar_t*)malloc(sizeof(wchar_t) * len+2);
unsigned char* newSrc = (unsigned char*)malloc(sizeof(unsigned char) * len + 2); MultiByteToWideChar(CP_UTF8, 0, src, -1, tmp, len); //转为unicode
WideCharToMultiByte(CP_ACP, 0, tmp, -1, newSrc, len+2, NULL,NULL); //转gbk return newSrc;
}
#endif void swap(unsigned char* a, unsigned char* b)
{
unsigned char t = *a;
*a = *b;
*b = t;
} //用key生成S盒
/*
* s: s盒
* key: 密钥
* len: 密钥长度
*/
void rc4Init(unsigned char* s, const unsigned char* key, int len)
{
int i = 0, j = 0;
unsigned char T[256] = { 0 }; for (i = 0; i < 256; i++)
{
s[i] = i;
T[i] = key[i % len];
} for (i = 0; i < 256; i++)
{
j = (j + s[i] + T[i]) % 256;
swap(s + i, s + j);
}
}
//针对NCM文件的解密
//异或关系
/*
* s: s盒
* data: 要加密或者解密的数据
* len: data的长度
*/
void rc4PRGA(unsigned char* s, unsigned char* data, int len)
{
int i = 0;
int j = 0;
int k = 0;
int idx = 0;
for (idx = 0; idx < len; idx++)
{
i = (idx + 1) % 256;
j = (i + s[i]) % 256;
k = (s[i] + s[j]) % 256;
data[idx] ^= s[k]; //异或
}
} //base64 解码
/*
* code: 要解码的数据
*/
unsigned char* base64_decode(unsigned char* code, int len, int* actLen)
{
//根据base64表,以字符找到对应的十进制数据
int table[] = { 0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,62,0,0,0,
63,52,53,54,55,56,57,58,
59,60,61,0,0,0,0,0,0,0,0,
1,2,3,4,5,6,7,8,9,10,11,12,
13,14,15,16,17,18,19,20,21,
22,23,24,25,0,0,0,0,0,0,26,
27,28,29,30,31,32,33,34,35,
36,37,38,39,40,41,42,43,44,
45,46,47,48,49,50,51
};
long str_len;
unsigned char* res;
int i, j; //计算解码后的字符串长度
//判断编码后的字符串后是否有=
if (strstr(code, "=="))
str_len = len / 4 * 3 - 2;
else if (strstr(code, "="))
str_len = len / 4 * 3 - 1;
else
str_len = len / 4 * 3; *actLen = str_len;
res = malloc(sizeof(unsigned char) * str_len + 1);
res[str_len] = '\0'; //以4个字符为一位进行解码
for (i = 0, j = 0; i < len - 2; j += 3, i += 4)
{
res[j] = ((unsigned char)table[code[i]]) << 2 | (((unsigned char)table[code[i + 1]]) >> 4);
res[j + 1] = (((unsigned char)table[code[i + 1]]) << 4) | (((unsigned char)table[code[i + 2]]) >> 2);
res[j + 2] = (((unsigned char)table[code[i + 2]]) << 6) | ((unsigned char)table[code[i + 3]]);
}
return res; }
void readFileData(const char* fileName)
{
FILE* f;
f = fopen(fileName, "rb");
if (!f)
{
printf("No such file: %s\n", fileName);
return;
} unsigned char buf[16];
int len=0;
int i = 0; unsigned char meta_key[] = { 0x23,0x31,0x34,0x6C,0x6A,0x6B,0x5F,0x21,0x5C,0x5D,0x26,0x30,0x55,0x3C,0x27,0x28 };
unsigned char core_key[] = { 0x68,0x7A,0x48,0x52,0x41,0x6D,0x73,0x6F,0x35,0x6B,0x49,0x6E,0x62,0x61,0x78,0x57 }; fseek(f, 10, SEEK_CUR); //f从当前位置移动10个字节
fread(buf, 1, 4, f); //读取rc4 key 的长度 len = (buf[3] << 8 | buf[2]) << 16 | (buf[1] << 8 | buf[0]);
unsigned char* rc4Key= (unsigned char*)malloc(sizeof(unsigned char) * len);
fread(rc4Key, 1, len, f); //读取rc4数据 //解密rc4密钥
for (i = 0; i < len; i++)
{
rc4Key[i] ^= 0x64;
} struct AES_ctx ctx;
AES_init_ctx(&ctx, core_key); //使用core_key密钥
int packSize = len / 16; //采用的是AES-ECB加密方式,和Pkcs7padding填充
for (i = 0; i < packSize; i++)
{
AES_ECB_decrypt(&ctx, &rc4Key[i * 16]);
}
int pad = rc4Key[len - 1]; //获取填充的长度
rc4Key[len - pad] = '\0'; //去除填充的部分,得到RC4密钥 fread(buf, 1, 4, f); //读取Music Info 长度数据
len = ((buf[3] << 8 | buf[2]) << 16) | (buf[1] << 8 | buf[0]);
unsigned char* meta = (unsigned char*)malloc(sizeof(unsigned char) * len);
fread(meta, 1, len, f); //读取Music Info数据
//解析Music info信息
for (i = 0; i < len; i++)
{
meta[i] ^= 0x63;
}
int act = 0;
unsigned char* data = base64_decode(&meta[22], len - 22, &act); //base64解码
AES_init_ctx(&ctx, meta_key); //AES解密
packSize = act / 16;
for (i = 0; i < packSize; i++)
{
AES_ECB_decrypt(&ctx, &data[i * 16]);
}
pad = data[act - 1];
data[act - pad] = '\0'; //去除填充部分
unsigned char* newData = data;
#ifdef WIN32 newData = utf8ToGbk(data, strlen(data)); #endif cJSON* cjson = cJSON_Parse(&newData[6]); //json解析,获取格式和名字等
if (cjson == NULL)
{
printf("cjson parse failed\n");
return;
}
//printf("%s\n", cJSON_Print(cjson)); //输出json fseek(f, 9, SEEK_CUR); //从当前位置跳过9个字节
fread(buf, 1, 4, f); //读取图片大小
len = (buf[3] << 8 | buf[2]) << 16 | (buf[1] << 8 | buf[0]);
unsigned char* img = (unsigned char*)malloc(sizeof(unsigned char) * len);
fread(img, 1, len, f); //读取图片数据 int offset= 1024 * 1024 * 10; //10MB 音乐数据一般比较大一次读入10MB
int total = 0;
int reSize = offset;
unsigned char* musicData = (unsigned char*)malloc(offset); //10m while (!feof(f))
{
len = fread(musicData+total, 1, offset, f); //每次读取10M
total += len;
reSize += offset;
musicData=realloc(musicData,reSize); //扩容
} unsigned char sBox[256] = { 0 }; //s盒
rc4Init(sBox, &rc4Key[17], strlen(&rc4Key[17])); //用rC4密钥进行初始化s盒
rc4PRGA(sBox, musicData, total); //解密 //拼接文件名(artist + music name+format)
char* musicName = cJSON_GetObjectItem(cjson, "musicName")->valuestring;
cJSON* sub = cJSON_GetObjectItem(cjson, "artist");
char*artist=cJSON_GetArrayItem(cJSON_GetArrayItem(sub, 0),0)->valuestring;
char* format = cJSON_GetObjectItem(cjson, "format")->valuestring;
char* saveFileName =(char*)malloc(strlen(musicName) + strlen(artist) + strlen(format)+5);
sprintf(saveFileName, "%s - %s.%s", artist, musicName, format);
FILE* fo=fopen(saveFileName, "wb");
if (fo == NULL)
{
printf("The fileName - '%s' is invalid in this system\n", saveFileName);
}
else
{
fwrite(musicData, 1, total, fo);
fclose(fo);
} #ifdef WIN32
free(newData);
#endif
free(data);
free(meta);
free(img);
free(musicData);
fclose(f); } int main(int argc,char**argv)
{
readFileData("結束バンド - ギターと孤独と蒼い惑星.ncm");
return 0;
}

GitHub项目

NcmToMp3

星期五女孩

网易云VIP音乐NCM文件转MP3,C语言版本。的更多相关文章

  1. 下载网易云VIP音乐

    有偿帮助.联系方式在个人信息里.

  2. 网易云音乐ncm格式分析以及ncm与mp3格式转换

    目录 NCM格式分析 音频知识简介 两种可能 GitHub项目 格式分析 总体结构 密钥问题 代码分析 main函数 导入模块 dump函数 参考资料 代码完整版 转换工具 ncmdump ncmdu ...

  3. 网易云音乐 歌词制作软件 BesLyric (最新版本下载)

    导读 BesLyric , 一款专门制作 网易云音乐 LRC 滚动歌词的软件! 搜索.下载.制作 歌词更方便! 哈哈,喜欢网易云音乐,又愁于制作歌词的童鞋有福啦!Beslyric 为你排忧解难! 本文 ...

  4. 网易云音乐PC客户端加密API逆向解析

    1.前言 网上已经有大量的web端接口解析的方法了,但是对客户端的接口解析基本上找不到什么资料,本文主要分析网易云音乐PC客户端的API接口交互方式. 通过内部的代理设置,使用fiddler作为代理工 ...

  5. Python 爬取网易云歌手的50首热门作品

    使用 requests 爬取网易云音乐 Python 代码: import json import os import time from bs4 import BeautifulSoup impor ...

  6. 网易云音乐ncm加密格式批量转换为flac,mp3

    从网易云下载的某些付费歌曲下载下来会是ncm格式.ncm是个啥?就是你下完一首歌被网易云加密成它自己独有的ncm格式,这个ncm不能在其他播放器播放,如果网易云你会员到期了同样也会提示你无法播放(不是 ...

  7. Python解密网易云音乐缓存文件获取MP3

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:GeneralMonkey Python解密网易云音乐缓存文件获取MP3 ...

  8. 教你PC端网易云音乐自定义代理,VIP免费听歌!

    今天分享一份福利吧,使用网易云音乐自定义代理实现免费听和下载VIP.极高音质.付费的歌曲,这里主要针对PC端电脑版的,需要自己写脚本运行. 01 安装node.js Node.js是一个让 JavaS ...

  9. 网易云音乐mp3外链、真实地址下载方法

    一个网易音乐外链地址长期有效,很简单的方法: 第一步打开网易云音乐,随便找到一首歌,播放,复制网址的ID, 例如:杨钰莹的心雨,网址是: http://music.163.com/#/song?id= ...

  10. 网易云音乐MP3外链地址

      网易云音乐MP3外链地址下载方法很简单的方法: 下载公式:http://music.163.com/song/media/outer/url?id=ID数字.mp3 把上面红色部分(ID数字)换成 ...

随机推荐

  1. [题解] Codeforces 1720 E Misha and Paintings 结论

    题目 算是诈骗题? 令一开始就存在的颜色数为cnt.k>=cnt的情况,显然每次找一个出现不止一次的颜色,然后把这个颜色的恰好一个方块替换成一种没有出现过的颜色就可以了,\(k-cnt\)次解决 ...

  2. 关于Linux下aws-cli-2版本的安装

    AWS CLI 版本 2 是 AWS CLI 的最新主版本,支持所有最新功能.版本 2 中引入的某些功能无法向后兼容版本 1,您必须升级才能访问这些功能. AWS CLI 版本 2 仅可作为捆绑安装程 ...

  3. 面向对象的照妖镜——UML类图绘制指南

    1.前言 感受 在刚接触软件开发工作的时候,每次接到新需求,在分析需求后的第一件事情,就是火急火燎的打开数据库(DBMS),开始进行数据表的创建工作.然而这种方式,总是会让我在编码过程中出现实体类设计 ...

  4. 华为设备配置和使用FTP服务命令

    配置SFTP Server与Client server:aaa 进入aaa视图 local-user huawei2 password cipher huawei2 设置用户名和密码 local-us ...

  5. 2022-08-21-Freewind主题_cdn替换版

    layout: post cid: 16 title: Freewind主题 cdn替换版 slug: 16 date: 2022/08/21 14:06:00 updated: 2022/08/21 ...

  6. Linux实战笔记_CentOS7_格式化磁盘

    fdisk -l #检查是否添加成功(添加一块磁盘并重启计算机后) fdisk /dev/sdb #格式化磁盘 mount /dev/sdb1 /opt #挂载到/opt目录 df -h #查看是否挂 ...

  7. F118校准(二)-- 操作步骤(使用任意品牌PG点屏,并使用PX01 PG校准F118)

    1. 准备工作 硬件连接: CA310通过USB线材连接PC PX01通过USB线材连接PC F118通过灰排线连接PX01左上角的GPIO扩展口(如下图所示) 启动LcdTools软件,点击&quo ...

  8. 10.异步mysql

    python中操作mysql连接.操作.断开都是网络IO #安装支持异步aiomysql的模块 pip3 install aiomysql async def execute(): # 网络IO操作, ...

  9. MySQL高可用集群MHA方案

    MySQL高可用集群MHA方案 爱奇艺在用的数据库高可用方案 MHA 是目前比较成熟及流行的 MySQL 高可用解决方案,很多互联网公司正是直接使用或者基于 MHA 的架构进行改造实现 MySQL 的 ...

  10. 二、Celery执行一步任务

    二.Celery执行异步任务 2.1.基本使用 创建项目celerypro 创建异步任务执行文件celery_task: import celery import time backend='redi ...