标签 Shell脚本 下的文章

本文为墨天轮数据库管理服务团队第162期技术分享,内容原创,作者为技术顾问闫建,如需转载请联系小墨(VX:modb666)并注明来源。如需查看更多文章可关注【墨天轮】公众号。

image.png

脚本功能

此脚本是专门用于MySQL8.0逻辑备份的 MySQL Shell备份脚本,它包含了备份数据库实例的所有对象,是整个实例级别的备份,也是当下取代传统mysqldump工具的最优替代方案。

脚本内容

该脚本名称为mysqlshell\_full\_backup.sh

#!/bin/bash
########################################
# MySQL Shell 自动备份脚本 (MySQL 8.0+)
# 功能: 全量逻辑备份 + 错误处理 + 日志记录 + 自动清理 + 时间统计
# 备份文件名格式: full_mysqlshell_backup_时间
# 使用方式: 直接修改脚本中的变量值,然后执行 ./mysqlshell_full_backup.sh
########################################
################### 配置参数 ###################
# MySQL Shell命令绝对路径(重要:请根据实际安装路径修改)
MYSQLSH_CMD="/data/soft/mysqlshell8044/bin/mysqlsh"
# 备份保留天数(默认15天)
RETAIN_DAYS=${RETAIN_DAYS:-15}
# 并行度(默认4线程)
PARALLEL=${PARALLEL:-4}
# 排除的数据库(逗号分隔,默认空)
EXCLUDE_SCHEMAS=${EXCLUDE_SCHEMAS:-""}
# 备份存储根目录
BACKUP_ROOT="/data/backup"
# 时间戳格式:YYYYMMDD_HHMMSS
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 备份目录名称(按您要求的格式)
BACKUP_DIR_NAME="full_mysqlshell_backup_${TIMESTAMP}"
BACKUP_DIR="${BACKUP_ROOT}/${BACKUP_DIR_NAME}"
# MySQL连接参数(请根据实际情况修改)
MYSQL_USER="root"
MYSQL_PASSWORD="mysql"
MYSQL_HOST="localhost"
MYSQL_PORT="3306"
# 日志文件路径
LOG_FILE="${BACKUP_ROOT}/backup.log"
############################################
########## 函数:记录日志 ##########
log() {
    local level="$1"
    local message="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local log_entry="[${timestamp}] [${level}] ${message}"
    # 输出到标准输出并写入日志文件
    echo "${log_entry}" | tee -a "${LOG_FILE}"
}
########## 函数:错误处理并退出 ##########
error_exit() {
    log "ERROR" "$1"
    end_time=$(date +%s)
    total_runtime=$((end_time - start_time_global))
    log "INFO" "脚本异常退出,总运行时间: $(format_duration $total_runtime)"
    exit 1
}
########## 函数:计算和格式化运行时间 ##########
format_duration() {
    local seconds=$1
    local hours=$((seconds / 3600))
    local minutes=$(( (seconds % 3600) / 60 ))
    local secs=$((seconds % 60))
    if [ $hours -gt 0 ]; then
        echo "${hours}小时${minutes}分${secs}秒"
    elif [ $minutes -gt 0 ]; then
        echo "${minutes}分${secs}秒"
    else
        echo "${secs}秒"
    fi
}
########## 函数:检查依赖工具 ##########
check_dependencies() {
    # 检查MySQL Shell是否存在且可执行
    if [ ! -x "$MYSQLSH_CMD" ]; then
        error_exit "MySQL Shell未在指定路径找到或不可执行: $MYSQLSH_CMD"
    fi
    # 检查其他依赖工具
    local deps=("du")
    for dep in "${deps[@]}"; do
        if ! command -v "$dep" &> /dev/null; then
            error_exit "所需工具 $dep 未安装或未在PATH中"
        fi
    done
    log "INFO" "依赖检查通过,MySQL Shell路径: $MYSQLSH_CMD"
}
########## 函数:检查MySQL连接 ##########
check_mysql_connection() {
    log "INFO" "检查MySQL数据库连接..."
    if "$MYSQLSH_CMD" --log-level=2 --uri="${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOST}:${MYSQL_PORT}" --sql --execute "select 1" >/dev/null 2>&1; then
        log "INFO" "MySQL数据库连接成功"
    else
        error_exit "MySQL数据库连接失败,请检查连接参数"
    fi
}
########## 函数:检查磁盘空间 ##########
check_disk_space() {
    local available_space=$(df "$BACKUP_ROOT" | awk 'NR==2 {print $4}')
    local min_space=$((1024 * 1024))  # 至少保留1GB空间
    if [ "$available_space" -lt "$min_space" ]; then
        error_exit "磁盘空间不足,剩余空间: ${available_space}KB,至少需要: ${min_space}KB"
    fi
    log "INFO" "磁盘空间检查通过,剩余空间: ${available_space}KB"
}
########## 主函数:执行备份 ##########
perform_backup() {
    log "INFO" "开始执行数据库备份..."
    # 构建excludeSchemas参数
    local exclude_param=""
    if [ -n "$EXCLUDE_SCHEMAS" ]; then
        local exclude_jsons=()
        IFS=',' read -ra DB_ARRAY <<< "$EXCLUDE_SCHEMAS"
        for db in "${DB_ARRAY[@]}"; do
            db_clean=$(echo "$db" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e "s/'/\\\\'/g")
            if [ -n "$db_clean" ]; then
                exclude_jsons+=("'$db_clean'")
            fi
        done
        if [ ${
#exclude
_jsons[@]} -gt 0 ]; then
            exclude_param="excludeSchemas: [$(IFS=,; echo "${exclude_jsons[*]}")],"
            log "INFO" "排除数据库: ${EXCLUDE_SCHEMAS}"
        fi
    fi
    # 构建备份命令
    local backup_cmd="util.dumpInstance('$BACKUP_DIR', { 
        threads: $PARALLEL, 
        ${exclude_param}
        consistent: true,
        compression: 'zstd',
        ocimds: true,
        compatibility: ['strip_restricted_grants','strip_definers','strip_tablespaces','ignore_missing_pks']
    })"
    log "INFO" "执行MySQL Shell备份命令,并行度: $PARALLEL"
    # 执行备份(使用变量化的MYSQLSH_CMD)
    if "$MYSQLSH_CMD" --log-level=3 --uri="${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOST}:${MYSQL_PORT}" \
        --execute "$backup_cmd" >> "$LOG_FILE" 2>&1; then
        log "INFO" "MySQL Shell备份命令执行完成"
        return 0
    else
        return 1
    fi
}
########## 主函数:清理过期备份 ##########
cleanup_old_backups() {
    log "INFO" "开始清理超过 ${RETAIN_DAYS} 天的旧备份..."
    local deleted_count=0
    while IFS= read -r -d '' old_backup; do
        if [ -n "$old_backup" ] && [ "$old_backup" != "$BACKUP_ROOT" ]; then
            log "INFO" "删除过期备份: $(basename "$old_backup")"
            rm -rf "$old_backup"
            ((deleted_count++))
        fi
    done < <(find "$BACKUP_ROOT" -maxdepth 1 -type d -name "full_mysqlshell_backup_*" -mtime "+$((RETAIN_DAYS-1))" -print0 2>/dev/null)
    log "INFO" "清理完成,共删除 $deleted_count 个过期备份"
}
########## 主执行流程 ##########
main() {
    local start_time_global=$(date +%s)
    log "INFO" "=== MySQL备份作业开始 ==="
    log "INFO" "备份目录: $BACKUP_DIR"
    log "INFO" "保留天数: $RETAIN_DAYS天, 并行度: $PARALLEL"
    log "INFO" "排除数据库: ${EXCLUDE_SCHEMAS:-无}"
    log "INFO" "MySQL Shell路径: $MYSQLSH_CMD"
    # 初始化检查
    check_dependencies
    check_disk_space
    check_mysql_connection
    # 创建备份目录
    if ! mkdir -p "$BACKUP_DIR"; then
        error_exit "无法创建备份目录: $BACKUP_DIR"
    fi
    log "INFO" "备份目录创建成功: $BACKUP_DIR"
    # 执行备份
    local backup_start=$(date +%s)
    if perform_backup; then
        local backup_end=$(date +%s)
        local backup_runtime=$((backup_end - backup_start))
        log "INFO" "数据库备份成功完成"
        log "INFO" "备份耗时: $(format_duration $backup_runtime)"
    else
        error_exit "数据库备份执行失败,详情请查看日志: $LOG_FILE"
    fi
    # 清理过期备份
    local cleanup_start=$(date +%s)
    cleanup_old_backups
    local cleanup_end=$(date +%s)
    local cleanup_runtime=$((cleanup_end - cleanup_start))
    # 最终统计
    local end_time_global=$(date +%s)
    local total_runtime=$((end_time_global - start_time_global))
    log "INFO" "=== 备份作业统计 ==="
    log "INFO" "备份文件位置: $BACKUP_DIR"
    log "INFO" "备份大小: $(du -sh "$BACKUP_DIR" 2>/dev/null | cut -f1 || echo "未知")"
    log "INFO" "各阶段耗时详情:"
    log "INFO" "  - 备份阶段: $(format_duration $backup_runtime)"
    log "INFO" "  - 清理阶段: $(format_duration $cleanup_runtime)"
    log "INFO" "  - 总计耗时: $(format_duration $total_runtime)"
    log "INFO" "日志文件: $LOG_FILE"
    log "INFO" "=== MySQL备份作业完成 ==="
}
########## 脚本执行入口 - 直接执行主函数 ##########
main

重点说明

1、关于备份时的参数说明

# 构建备份命令
local backup_cmd="util.dumpInstance('$BACKUP_DIR', { 
    threads: $PARALLEL, 
    ${exclude_param}
    consistent: true,
    compression: 'zstd',
    ocimds: true,
    compatibility: ['strip_restricted_grants','strip_definers','strip_tablespaces','ignore_missing_pks']
})"

上面构建备份语句中,有一个兼容性参数设置compatibility,该参数需要额外说明:

  • strip\_restricted\_grants 移除备份文件中,目标数据库服务不允许授予的高级权限,避免因权限问题导致导入失败
  • strip\_definers 从视图、存储过程等对象定义中移除 DEFINER=子句,避免因原始定义者不存在而导致的权限错误
  • strip\_tablespaces 从建表语句中移除 TABLESPACE=子句,此选项可防止因指定不存在的表空间而导致建表失败
  • ignore\_missing\_pks 忽略(跳过检查)没有主键的表,而不为它们自动创建主键,用于容忍没有主键的表,但不会自动修复。如需自动添加主键,应使用 create\_invisible\_pks选项
     

2、关于备份软件的说明

MySQL数据库软件并不自带MySQLShell功能,MySQL Shell软件需要提前下载准备好,下载链接如下:

https://dev.mysql.com/downloads/shell/

image.png

MySQLShell软件下载到本地服务器后,解压即可使用非常简单方便。

使用方法

如采用压缩备份,此步骤为必须执行步骤,非压缩备份,此步

1、保存脚本并赋予执行权限

[root@VM-8-4-opencloudos backup]# chmod +x mysqlshell_full_backup.sh

2、可选手动执行备份

[root@VM-8-4-opencloudos backup]# ./mysqlshell_full_backup.sh

image.png

tail -100 /data/backup/backup.log

image.png

3. 可配置定时任务(每日凌晨1点执行)

# 编辑crontab:crontab -e 添加如下内容并保存
01 * * * /path/to/mysqlshell_full_backup.sh

恢 复

作为DBA,恢复工作需要严谨的操作流程。以下是基于该备份的详细恢复步骤和指南。

1、确认备份文件的完整性

在开始恢复前,务必检查备份目录是否完整。一个成功的 util.dumpInstance备份通常会包含一个 @.done.json文件以及每个数据库对应的 .tsv.zst数据文件和 .sql元数据文件。您可以使用以下命令快速查看备份根目录下的内容:

[root@VM-8-4-opencloudos backup]# ls -l full_mysqlshell_backup_20251113_111713
total 23624
-rw-r----- 1 root root      549 Nov 13 11:17 @.done.json
-rw-r----- 1 root root     1400 Nov 13 11:17 @.json
-rw-r----- 1 root root      240 Nov 13 11:17 @.post.sql
-rw-r----- 1 root root      240 Nov 13 11:17 @.sql
-rw-r----- 1 root root        9 Nov 13 11:17 testdb@a@@0.tsv.zst
-rw-r----- 1 root root        8 Nov 13 11:17 testdb@a@@0.tsv.zst.idx
-rw-r----- 1 root root      612 Nov 13 11:17 testdb@a.json
-rw-r----- 1 root root      750 Nov 13 11:17 testdb@a.sql
-rw-r----- 1 root root        9 Nov 13 11:17 testdb@b@@0.tsv.zst
-rw-r----- 1 root root        8 Nov 13 11:17 testdb@b@@0.tsv.zst.idx
-rw-r----- 1 root root      562 Nov 13 11:17 testdb@b.json
-rw-r----- 1 root root      644 Nov 13 11:17 testdb@b.sql
-rw-r----- 1 root root      585 Nov 13 11:17 testdb.json
-rw-r----- 1 root root 23971894 Nov 13 11:17 testdb@large_table@@0.tsv.zst
-rw-r----- 1 root root      544 Nov 13 11:17 testdb@large_table@@0.tsv.zst.idx
-rw-r----- 1 root root     1036 Nov 13 11:17 testdb@large_table.json
-rw-r----- 1 root root     1418 Nov 13 11:17 testdb@large_table.sql
-rw-r----- 1 root root    92884 Nov 13 11:17 testdb@my_table@@0.tsv.zst
-rw-r----- 1 root root        8 Nov 13 11:17 testdb@my_table@@0.tsv.zst.idx
-rw-r----- 1 root root      890 Nov 13 11:17 testdb@my_table.json
-rw-r----- 1 root root     1349 Nov 13 11:17 testdb@my_table.sql
-rw-r----- 1 root root     4038 Nov 13 11:17 testdb.sql
-rw-r----- 1 root root       14 Nov 13 11:17 testdb@tt@@0.tsv.zst
-rw-r----- 1 root root        8 Nov 13 11:17 testdb@tt@@0.tsv.zst.idx
-rw-r----- 1 root root      583 Nov 13 11:17 testdb@tt.json
-rw-r----- 1 root root       19 Nov 13 11:17 testdb@tt_new@@0.tsv.zst
-rw-r----- 1 root root        8 Nov 13 11:17 testdb@tt_new@@0.tsv.zst.idx
-rw-r----- 1 root root      587 Nov 13 11:17 testdb@tt_new.json
-rw-r----- 1 root root      686 Nov 13 11:17 testdb@tt_new.sql
-rw-r----- 1 root root      674 Nov 13 11:17 testdb@tt.sql
-rw-r----- 1 root root     4344 Nov 13 11:17 @.users.sql

2、准备恢复环境

  • 目标MySQL实例:确保用于恢复的MySQL服务已启动并可以正常连接。它最好与源服务器版本一致或兼容,以避免潜在问题。
  • 权限检查:用于执行恢复操作的MySQL账户需要具备足够的权限,例如 SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, 甚至可能需要 RELOAD或 SUPER权限。
  • 磁盘空间:确保目标实例的磁盘有足够空间容纳要恢复的数据。
  • 决策:完全恢复还是部分恢复? 想清楚是需要恢复整个实例,还是只恢复其中的一个或多个特定数据库。这决定了后续使用的工具和命令。
## 说明:在导入数据之前,建议检查参数local_infile是否开启,如未开启,需要进行提前设置。
root@localhost:(none) 02:01:54 > show global variables like '%local_infile%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| local_infile  | OFF   |
+---------------+-------+
1 row in set (0.11 sec)
root@localhost:(none) 02:01:46 >set global local_infile=1;
Query OK, 0 rows affected (0.00 sec)

3、恢复操作步骤

MySQL Shell工具软件进行备份,恢复时候也必须使用MySQL Shell进行恢复,这个是必须满足的基本条件。

  • 恢复方式一:

在服务器上执行以下命令。请务必将 备份目录路径、用户名、密码、主机和 端口替换为您的实际信息。

mysqlsh -u root -p --host localhost --port 3306 --js
--进入 MySQL Shell 的 JavaScript 模式后,执行:
util.loadDump("/data/backup/full_mysqlshell_backup_20251113_103022", {
    threads: 4,        // 并行线程数,可调整
    skipBinlog: false, // 如果恢复过程不想记录到二进制日志,可设为true
    ignoreVersion: true, // 忽略MySQL版本差异警告(谨慎使用)
    resetProgress: true  // 如果重新开始一个恢复,重置进度
});
  • 恢复方式二:
mysqlsh -u root -p -h localhost -P 3306 --js -e "util.loadDump('/data/backup/full_mysqlshell_backup_20251113_103022', {threads: 4, skipBinlog: false})"

4、监控恢复过程

恢复过程中,util.loadDump会显示进度信息。您也可以在另一个会话中连接到MySQL,使用 sql模式查看正在创建的表或进程。
image.png

总 结

该脚本提供了一个生产环境使用MySQL Shell 工具对 MySQL8.0版本进行逻辑备所需的完整步骤,包括错误处理、日志记录、自动清理和耗时统计以及最后的恢复步骤。数据库运维人员可以根据实际环境调整配置参数,特别是备份路径和保留天数设置等一些常用功能的设置。


墨天轮从乐知乐享的数据库技术社区蓄势出发,全面升级,提供多类型数据库管理服务。墨天轮数据库管理服务旨在为用户构建信赖可托付的数据库环境,并为数据库厂商提供中立的生态支持。
墨天轮数据库服务官网:https://www.modb.pro/service

大家好,我是良许。

最近收到不少粉丝的私信,问得最多的就是:"良许,嵌入式方向这么多,我到底该选哪个?"说实话,这个问题我当年也纠结过。

今天就结合我这些年的经验,跟大家好好聊聊嵌入式就业方向的选择问题。

1. 嵌入式领域的主流方向

1.1 单片机开发方向

这是我入行时的第一个方向。

单片机开发主要是基于STM32、51单片机、PIC等芯片进行底层开发,通常应用在智能家居、工业控制、医疗设备等领域。

这个方向的特点是门槛相对较低,但要做精也不容易。

你需要掌握C语言、硬件电路知识、各种外设驱动(GPIO、UART、SPI、I2C等)。

举个例子,用STM32的HAL库点个灯看起来简单:

// 初始化GPIO
void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 主循环控制LED闪烁
int main(void)
{
    HAL_Init();
    LED_Init();
    
    while(1)
    {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
        HAL_Delay(500);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
        HAL_Delay(500);
    }
}

但实际项目中,你要处理的是复杂的通信协议、实时性要求、功耗优化、抗干扰设计等问题。

这个方向的薪资在一线城市应届生大概8K-12K,3年经验能到15K-20K。

1.2 嵌入式Linux应用开发

这是我27岁进入外企后的主要方向,也是目前市场需求最大的方向之一。

主要工作是在Linux系统上开发应用程序,涉及文件IO、进程线程、网络编程、数据库操作等。

这个方向需要你熟悉Linux系统编程、Shell脚本、网络协议栈、多线程编程等。

比如一个简单的多线程读取传感器数据的例子:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void* sensor_read_thread(void* arg)
{
    int sensor_id = *(int*)arg;
    while(1)
    {
        // 模拟读取传感器数据
        printf("Sensor %d: Reading data...\n", sensor_id);
        sleep(1);
    }
    return NULL;
}

int main()
{
    pthread_t thread1, thread2;
    int sensor1 = 1, sensor2 = 2;
    
    pthread_create(&thread1, NULL, sensor_read_thread, &sensor1);
    pthread_create(&thread2, NULL, sensor_read_thread, &sensor2);
    
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    
    return 0;
}

这个方向在汽车电子、智能设备、工业互联网等领域应用广泛。

薪资方面,应届生大概10K-15K,3年经验能达到20K-30K,在外企或大厂甚至更高。

1.3 嵌入式Linux驱动开发

这是嵌入式领域的高端方向,主要负责编写Linux内核驱动程序,让硬件设备能够在Linux系统上正常工作。

需要深入理解Linux内核机制、硬件原理、驱动框架等。

驱动开发的难度比较大,需要掌握内核模块编程、设备树、中断处理、DMA等知识。

一个简单的字符设备驱动框架:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>

static dev_t dev_num;
static struct cdev my_cdev;

static int my_open(struct inode *inode, struct file *file)
{
    printk("Device opened\n");
    return 0;
}

static ssize_t my_read(struct file *file, char __user *buf, 
                       size_t count, loff_t *ppos)
{
    printk("Device read\n");
    return 0;
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = my_open,
    .read = my_read,
};

static int __init my_driver_init(void)
{
    alloc_chrdev_region(&dev_num, 0, 1, "my_device");
    cdev_init(&my_cdev, &fops);
    cdev_add(&my_cdev, dev_num, 1);
    return 0;
}

module_init(my_driver_init);

这个方向的薪资是嵌入式领域最高的之一,有3-5年经验的驱动工程师在一线城市能拿到25K-40K,资深的甚至能达到50K以上。

1.4 RTOS实时操作系统开发

RTOS方向主要应用在对实时性要求极高的场景,比如航空航天、医疗设备、工业控制等。常用的RTOS有FreeRTOS、RT-Thread、μC/OS等。

这个方向需要理解任务调度、信号量、消息队列、内存管理等概念。

FreeRTOS的一个简单任务创建示例:

#include "FreeRTOS.h"
#include "task.h"

void vTask1(void *pvParameters)
{
    while(1)
    {
        printf("Task 1 running\n");
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void vTask2(void *pvParameters)
{
    while(1)
    {
        printf("Task 2 running\n");
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

int main(void)
{
    xTaskCreate(vTask1, "Task1", 128, NULL, 1, NULL);
    xTaskCreate(vTask2, "Task2", 128, NULL, 2, NULL);
    
    vTaskStartScheduler();
    
    while(1);
}

RTOS方向的薪资水平介于单片机和Linux之间,应届生大概9K-13K,3年经验能到18K-25K。

1.5 汽车电子方向

这是我目前深耕的领域。

汽车电子包括ADAS(高级驾驶辅助系统)、车载娱乐系统、动力系统控制等。

需要了解AUTOSAR架构、CAN/LIN总线、车规级开发流程等。

汽车电子对可靠性和安全性要求极高,需要遵循ISO 26262等功能安全标准。

这个方向的技术栈比较综合,既要懂硬件,又要懂软件,还要了解汽车行业的特殊要求。

薪资方面,汽车电子在传统车企可能不算特别高,但在新能源车企和Tier1供应商,待遇还是很不错的。

应届生大概10K-14K,3年经验能达到20K-30K,资深工程师35K以上。

2. 如何选择适合自己的方向

2.1 根据兴趣和特长选择

如果你喜欢硬件,动手能力强,喜欢焊电路板、调试硬件,那单片机或RTOS方向可能更适合你。

如果你更喜欢软件编程,喜欢研究算法和系统架构,那Linux应用或驱动开发会是更好的选择。

我当年选择Linux方向,就是因为发现自己更擅长软件编程,对底层原理也很感兴趣。

虽然本科学的是机械,但编程让我找到了真正的兴趣所在。

2.2 考虑市场需求和发展前景

从市场需求来看,目前嵌入式Linux开发的岗位最多,尤其是在物联网、智能设备、汽车电子等领域。

单片机开发虽然岗位也不少,但相对来说技术含量和薪资天花板会低一些。

驱动开发岗位相对较少,但薪资高,竞争也激烈。

RTOS方向比较小众,但在特定领域(如航空航天、医疗设备)有不可替代的地位。

汽车电子是近几年的热门方向,随着新能源汽车和智能驾驶的发展,这个领域的需求还在持续增长。

如果你看好汽车行业的未来,这是个不错的选择。

2.3 评估学习难度和时间成本

单片机开发入门相对容易,几个月的学习就能上手做项目。

Linux应用开发需要半年到一年的系统学习。

驱动开发难度最大,可能需要1-2年的深入学习和实践。

我的建议是,如果你是应届生或转行新手,可以先从单片机或Linux应用入手,积累一定经验后再考虑往更深的方向发展。

我自己就是这样走过来的,先做单片机,再做Linux应用,现在也在不断学习驱动相关的知识。

2.4 考虑地域因素

不同城市对不同方向的需求也不一样。

北京、上海、深圳、杭州等一线城市,各个方向的岗位都比较多。

但如果你在二三线城市,可能单片机和工业控制方向的岗位会更多一些。

我在福州,这边汽车电子和工业控制的公司比较多,所以我选择深耕汽车电子方向。

你也要结合自己所在城市或打算去的城市来考虑。

3. 我的一些建议

3.1 不要过早限制自己

很多人一开始就想选定一个方向,然后一直做下去。

但实际上,嵌入式的各个方向是相通的,底层的C语言、数据结构、操作系统原理都是共通的。

我的经历就是最好的例子。

虽然我现在主要做Linux应用开发,但单片机的经验让我对硬件有更深的理解,这在做Linux开发时也很有帮助。

所以不要害怕尝试不同的方向,每一段经历都是财富。

3.2 重视基础知识的学习

无论选择哪个方向,C语言、数据结构、操作系统原理、计算机网络这些基础知识都是必须掌握的。

很多人急于学习具体的技术,却忽视了基础,这样后期的发展会受限。

我在写公众号的过程中,发现很多读者的问题其实都是基础不扎实导致的。

所以我一直强调,要花时间把基础打牢,这比学习具体的技术更重要。

3.3 多做项目,积累经验

理论学习固然重要,但嵌入式是一个实践性很强的领域。

你需要通过做项目来巩固知识,发现问题,解决问题。

可以从简单的项目开始,比如用STM32做一个温湿度监测系统,用树莓派做一个智能家居控制器。

然后逐步增加难度,做一些综合性的项目。

我当年就是通过做各种小项目,慢慢积累起来的。

3.4 关注行业动态,持续学习

嵌入式领域的技术更新很快,新的芯片、新的操作系统、新的开发工具层出不穷。

你需要保持学习的习惯,关注行业动态,了解新技术的发展。

我现在每天都会花时间看技术文章、学习新知识。虽然工作很忙,但学习不能停。

这也是我为什么要做公众号的原因之一,通过写作来倒逼自己学习,同时也能帮助更多的人。

3.5 建立自己的技术体系

随着经验的积累,你需要建立自己的技术体系,形成自己的技术壁垒。

这不仅仅是掌握某个具体的技术,而是要有系统的思维,能够解决复杂的问题。

比如我现在做嵌入式Linux开发,不仅要会写应用程序,还要了解底层驱动、内核机制、硬件原理。

这样在遇到问题时,我能够从多个角度去分析和解决。

这种综合能力是需要长期积累的。

4. 写在最后

嵌入式就业方向的选择,没有绝对的好坏,只有适合不适合。

关键是要了解自己的兴趣和特长,结合市场需求和发展前景,做出适合自己的选择。

我从机械转到嵌入式,从单片机做到Linux,从打工到创业,这一路走来,最大的感悟就是:选择很重要,但更重要的是选择之后的坚持和努力。

无论你选择哪个方向,只要用心去做,都能做出成绩。

希望这篇文章能给你一些启发和帮助。

如果你还有其他问题,欢迎在评论区留言,我会尽力解答。

也欢迎关注我的公众号,我会持续分享嵌入式相关的技术文章和经验心得。

最后,祝大家都能找到适合自己的方向,在嵌入式领域走得更远!

更多编程学习资源

各位大佬好!最近笔记本更换了系统,从 Windows 换到了 Deepin 25。

以前在 Win 下习惯用 AHK 自动化,现在发现 Deepin 使用.sh 脚本非常强大,虽然完全没有编程基础,但主打一个折腾。随即尝试用 AI 帮我写脚本,结果可想而知:

就这一个脚本都磕磕绊绊、缝缝补补一两个月 (每天折腾一小会)。
后知后觉意识到不是 AI 不行,而是我作为 “提问者” 词不达意,不懂如何给 AI 下达清晰的指令。

想请教各位大佬:

  1. 入门路径: 想要系统性地提升 “提问力”,有没有公认的底层逻辑或框架值得学习?(比如大家常说的结构化提示词)

  2. 思维转变: 面对 AI 时,如何把模糊的需求拆解成它能听懂的逻辑指令?

  3. 进阶建议: 大家平时是如何打磨提示词的?有没有什么高质量的教程或者实战心得可以分享?

希望有经验的大佬指点迷津,在此谢过!

帖子也是通过 GPT 优化了一下,希望大佬们不要介意
快捷.txt


📌 转载信息
原作者:
15sir
转载时间:
2026/1/18 15:49:18