bash语法与init.rc语法对比

  1. bash语法 bash是一种Unix shell,用于交互式命令执行和脚本编程。其语法包括变量、条件判断、循环、函数等。

  2. init.rc语法 init.rc是Android初始化语言(Android Init Language)的脚本,用于系统启动时配置系统服务、执行命令等。它的语法相对简单,主要包含动作(action)、服务(service)、命令(command)和选项(option)。

区别概述: 用途:bash用于通用脚本编程,而init.rc用于Android系统初始化。

语法结构:bash具有复杂的编程结构(如循环、条件、函数),init.rc则是声明式的,主要定义服务、触发器和命令。

执行环境:bash脚本在shell中运行,init.rc由init进程解析并执行。

bash语法与init.rc语法对比指南

一、bash语法基础

1. 变量操作

bash 复制代码
#!/bin/bash
# 这是bash脚本的注释

# 变量定义(=前后不能有空格)
name="World"
count=10

# 使用变量
echo "Hello, $name"      # 输出: Hello, World
echo "Count: ${count}"   # 输出: Count: 10

# 只读变量
readonly PI=3.14
# PI=3.1415  # 这行会报错

# 删除变量(不能删除只读变量)
unset count
echo "Count: $count"     # 输出: Count: (空)

执行结果:

复制代码
Hello, World
Count: 10
Count: 

2. 条件判断

bash 复制代码
#!/bin/bash

num=10

# if-elif-else结构
if [ $num -gt 5 ]; then
    echo "数字大于5"      # 输出: 数字大于5
elif [ $num -eq 5 ]; then
    echo "数字等于5"
else
    echo "数字小于5"
fi

# 字符串比较
str="hello"
if [ "$str" = "hello" ]; then
    echo "字符串匹配"      # 输出: 字符串匹配
fi

# 文件测试
if [ -f "/etc/passwd" ]; then
    echo "文件存在"        # 输出: 文件存在
fi

执行结果:

复制代码
数字大于5
字符串匹配
文件存在

3. 循环结构

bash 复制代码
#!/bin/bash

# for循环
echo "for循环示例:"
for i in 1 2 3 4 5
do
    echo "数字: $i"      # 输出1-5
done

# while循环
echo -e "\nwhile循环示例:"
counter=1
while [ $counter -le 3 ]
do
    echo "计数: $counter"  # 输出1-3
    ((counter++))         # bash算术运算
done

# until循环
echo -e "\nuntil循环示例:"
num=1
until [ $num -gt 3 ]
do
    echo "直到: $num"     # 输出1-3
    num=$((num + 1))
done

执行结果:

复制代码
for循环示例:
数字: 1
数字: 2
数字: 3
数字: 4
数字: 5

while循环示例:
计数: 1
计数: 2
计数: 3

until循环示例:
直到: 1
直到: 2
直到: 3

4. 函数定义

bash 复制代码
#!/bin/bash

# 函数定义
greet() {
    local name=$1  # 局部变量
    echo "Hello, $name!"
    return 0       # 返回状态码
}

# 调用函数
greet "Alice"      # 输出: Hello, Alice!
greet "Bob"        # 输出: Hello, Bob!

# 获取返回值
echo "函数返回值: $?"  # 输出: 函数返回值: 0

执行结果:

复制代码
Hello, Alice!
Hello, Bob!
函数返回值: 0

二、init.rc语法基础

1. 基本结构

rc 复制代码
# init.rc注释以#开头
# 这是Android初始化语言

# 定义服务
service myservice /system/bin/myapp    # 服务名和可执行路径
    class main                         # 服务类
    user root                          # 运行用户
    group root                         # 运行组
    oneshot                            # 只运行一次

# 触发器和动作
on boot                                # 当boot事件触发时
    start myservice                    # 启动服务
    mkdir /data/mydir 0775 root root   # 创建目录

on property:sys.boot_completed=1       # 属性条件触发
    stop myservice                     # 停止服务

2. 完整init.rc示例

rc 复制代码
# 系统初始化脚本示例

# 导入其他rc文件
import /init.${ro.hardware}.rc

# 设置环境变量
export PATH /sbin:/system/bin:/system/xbin

# 创建设备节点
mkdir /dev/socket 0775 system system

# 挂载文件系统
mount tmpfs tmpfs /mnt mode=0755,uid=0,gid=0

# 定义系统服务
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main                    # 属于main类
    socket zygote stream 660 root system  # 创建socket
    onrestart restart media       # 重启时重启media服务
    writepid /dev/cpuset/foreground/tasks  # 写入pid文件

# 定义普通服务
service my_daemon /system/bin/my_daemon
    class core                   # 属于core类
    user system                  # 以system用户运行
    group system                 # 以system组运行
    disabled                     # 默认不启动
    capabilities NET_BIND_SERVICE  # 设置capabilities

# 触发器定义
on early-init                    # 早期初始化阶段
    # 设置安全上下文
    setcon u:r:init:s0
    # 启动ueventd
    start ueventd

on init                         # 初始化阶段
    # 挂载必要的文件系统
    mount proc /proc proc nosuid,nodev,noexec
    mount sysfs /sys sysfs nosuid,nodev,noexec
    mount devpts /dev/pts devpts mode=0620,gid=5

on late-init                    # 后期初始化
    # 触发其他事件
    trigger post-fs
    trigger load_system_props

on property:persist.sys.debug=1  # 属性触发
    # 设置调试模式
    setprop debug.trace 1
    start debug_service

on post-fs-data                 # 文件系统数据挂载后
    # 设置目录权限
    chown system system /data/app
    chmod 0771 /data/app

# 命令序列
on boot
    # 启动基本服务
    class_start core           # 启动core类所有服务
    class_start main           # 启动main类所有服务
    
    # 设置系统属性
    setprop sys.boot_completed 0
    
    # 执行shell命令
    exec /system/bin/logwrapper /system/bin/sh /system/etc/init.sh

3. init.rc特有的命令

rc 复制代码
# 常用init.rc命令示例

# 1. 服务控制命令
start <servicename>           # 启动服务
stop <servicename>            # 停止服务
restart <servicename>         # 重启服务

# 2. 类控制命令
class_start <classname>       # 启动类中所有服务
class_stop <classname>        # 停止类中所有服务
class_reset <classname>       # 重置类中所有服务

# 3. 属性操作
setprop <name> <value>        # 设置属性
getprop <name>                # 获取属性

# 4. 文件系统操作
mkdir <path> [mode] [owner] [group]  # 创建目录
chown <owner> <group> <path>         # 修改所有者
chmod <mode> <path>                  # 修改权限
mount <type> <device> <dir> [flags]  # 挂载文件系统

# 5. 其他命令
write <path> <string>         # 写文件
copy <src> <dst>              # 复制文件
symlink <target> <path>       # 创建软链接

三、核心区别对比表

特性 bash语法 init.rc语法
用途 通用shell脚本 Android系统初始化
执行环境 bash解释器 init进程
注释 #开头 #开头
变量定义 name="value" setprop name value
条件判断 if [条件]; then on property:name=value
循环结构 for, while, until 不支持循环
函数定义 function name() { } 不支持函数
服务定义 无内置概念 service name path [args]
触发机制 需手动调用 基于事件/属性触发
并行执行 需要特殊处理 支持服务并行启动
返回值 $?获取返回值 通过属性或状态码

四、综合示例对比

bash版本的服务管理脚本:

bash 复制代码
#!/bin/bash
# bash服务管理脚本

# 定义服务列表
SERVICES=("nginx" "mysql" "redis")

# 启动所有服务
start_services() {
    echo "开始启动服务..."
    for service in "${SERVICES[@]}"; do
        if systemctl start "$service"; then
            echo "✓ $service 启动成功"
        else
            echo "✗ $service 启动失败"
            return 1
        fi
    done
    return 0
}

# 检查服务状态
check_services() {
    echo "检查服务状态:"
    for service in "${SERVICES[@]}"; do
        if systemctl is-active --quiet "$service"; then
            echo "✓ $service 运行中"
        else
            echo "✗ $service 未运行"
        fi
    done
}

# 主逻辑
case "$1" in
    start)
        start_services
        ;;
    status)
        check_services
        ;;
    *)
        echo "用法: $0 {start|status}"
        exit 1
        ;;
esac

init.rc版本的服务管理:

rc 复制代码
# init.rc服务配置

# 定义服务
service nginx /usr/sbin/nginx
    class main
    user www-data
    group www-data
    oneshot

service mysql /usr/sbin/mysqld
    class main
    user mysql
    group mysql
    socket mysqld stream 660 mysql mysql

service redis /usr/bin/redis-server
    class main
    user redis
    group redis

# 启动控制
on boot
    class_start main

on property:sys.service.stop=1
    class_stop main

on property:sys.service.restart=1
    class_stop main
    class_start main

五、学习建议

学习bash:

  1. 重点掌握:变量、条件判断、循环、函数、命令替换
  2. 实践方法:在Linux终端编写测试脚本
  3. 调试技巧 :使用set -x调试,echo输出中间值

学习init.rc:

  1. 重点掌握:service定义、触发器、属性系统、基本命令
  2. 实践方法:在Android源码环境下测试
  3. 调试技巧:通过logcat查看init进程日志

共同点:

  • 都以#开头注释
  • 都有基本的条件执行逻辑
  • 都支持执行系统命令

关键差异:

  • bash是完整的编程语言,init.rc是声明式配置语言
  • bash侧重流程控制,init.rc侧重服务管理和系统配置
  • bash在用户空间运行,init.rc在内核初始化阶段运行

通过对比学习,你可以根据实际需求选择合适的语法:系统初始化用init.rc,自动化脚本用bash。

相关推荐
9ilk37 分钟前
【C++】--- 类型转换
开发语言·c++
悟能不能悟41 分钟前
目前流行的前端框架
开发语言·javascript·ecmascript
计算机学姐43 分钟前
基于Python的智能点餐系统【2026最新】
开发语言·vue.js·后端·python·mysql·django·flask
risc12345644 分钟前
【备忘录】java.lang.Throwable#addSuppressed这个是干嘛的?
java·开发语言
宵时待雨44 分钟前
C语言笔记归纳17:数据的存储
c语言·开发语言·笔记
7ioik1 小时前
什么是双亲委派?
开发语言·python
傻啦嘿哟1 小时前
Python高效实现Excel与TXT文本文件数据转换指南
开发语言·python·excel
七宝大爷1 小时前
第一个CUDA程序:从向量加法开始
android·java·开发语言
木心爱编程1 小时前
Qt C++ 插件开发指南:插件架构设计与动态加载实战
开发语言·c++·qt