OpenHarmony应用层调用Shell指令指南

文档概述
说明:

1.文章由移远通信技术股份有限公司提供
2.以下内容包含了个人理解,仅供参考,如有不合理处,请联系笔者修改18770704023(微信同号)

目录

  1. 前言与背景
  2. 开发环境
  3. 调用方法
  4. 注意事项
  5. 总结

前言与背景

在OpenHarmony应用开发过程中,开发者经常会遇到系统API无法直接实现某些功能,但通过Shell命令可以实现的场景。本文档旨在提供几种在应用层调用Shell命令的方法,帮助开发者解决这类问题。

开发环境

  • 系统版本:OpenHarmony 5.0.3
  • 开发语言:ArkTS (ETS)、C++
  • 编译环境:Ubuntu 20.04.6 LTS
  • 涉及模块:ArkUI、Native C++

调用方法

方法一:使用C/C++标准库函数system()

实现步骤

  1. 创建Native C++工程

    在这里插入图片描述

  2. 在napi_init.cpp文件中添加实现

#include <cstdlib>

static napi_value ExecuteShell(napi_env env, napi_callback_info info)
{
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    if (argc < 1) {
        napi_value result;
        napi_create_int32(env, -1, &result);
        return result;
    }

    size_t str_len = 0;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &str_len);
    
    char* command = new char[str_len + 1];
    napi_get_value_string_utf8(env, args[0], command, str_len + 1, nullptr);

    int result = system(command);
    
    delete[] command;

    napi_value ret;
    napi_create_int32(env, result, &ret);
    return ret;
}
  1. 在ArkTS中调用
// 示例:调用bootanimation指令
let result: number = testNapi.executeShell('/system/bin/bootanimation');
// 其他可调用的命令示例:reboot等

特点

  • 优点:实现简单,适用于不需要获取命令输出的场景
  • 缺点:无法获取命令执行的输出信息,仅返回执行状态码

注意:要在build-profile.json5文件里对abiFilters进行配置,不然调用接口的时候应用会闪退并报错

方法二:使用C/C++标准库函数popen()

实现步骤

  1. 在napi_init.cpp文件中添加实现
#include <cstdio>
#include <string>

static napi_value ExecuteShell2(napi_env env, napi_callback_info info)
{
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    if (argc < 1) {
        napi_value result;
        napi_create_string_utf8(env, "Error: No command provided", NAPI_AUTO_LENGTH, &result);
        return result;
    }

    size_t str_len = 0;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &str_len);
    
    char* command = new char[str_len + 1];
    napi_get_value_string_utf8(env, args[0], command, str_len + 1, nullptr);

    // 使用popen捕获命令输出
    FILE* pipe = popen(command, "r");
    if (!pipe) {
        delete[] command;
        napi_value result;
        napi_create_string_utf8(env, "Error: Failed to execute command", NAPI_AUTO_LENGTH, &result);
        return result;
    }

    char buffer[128];
    std::string output = "";
    while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
        output += buffer;
    }
    pclose(pipe);

    delete[] command;

    napi_value ret;
    napi_create_string_utf8(env, output.c_str(), NAPI_AUTO_LENGTH, &ret);
    return ret;
}
  1. 在ArkTS中调用
// 示例:获取当前日期时间
let dateResult: string = testNapi.executeShell2('/system/bin/date');
// 示例:列出目录内容
let lsResult: string = testNapi.executeShell2('/system/bin/ls');
// 示例:获取当前工作目录
let pwdResult: string = testNapi.executeShell2('pwd');

特点

  • 优点:可以获取命令执行的输出信息,适用于需要处理命令结果的场景
  • 缺点:实现相对复杂,需要处理文件流

方法三:通过系统属性触发指令

实现步骤

  1. 创建配置文件
    • 创建amixer_commands.cfg文件
    • 通过build.gn内置到system/etc/init目录
{
    "jobs" : [
        {
            "name" : "param:sys.amixer.commands=0",
            "condition" : "sys.amixer.commands=0",
            "cmds" : [
                "start execute_amixer_command0"
            ]
        }
    ], 
    "services" : [{
        "name" : "execute_amixer_command0",
        "start-mode" : "condition",
        "path": [
            "/system/bin/sh",
            "-c",
            "amixer cset name='VBC DAC0 DG Set' 0 0"
        ],
        "disabled" : 1,
        "sandbox" : 0,
        "uid" : "root",
        "gid" : ["shell"],
        "once" : 1,
        "secon" : "u:r:su:s0"
    }]
}
  1. 在ArkTS中调用
import systemParameterEnhance from '@ohos.systemParameterEnhance';

// 设置系统属性触发指令
systemParameterEnhance.setSync("sys.amixer.commands", "0");
  1. 添加白名单
    • vendor/产品名/high_privilege_process_list.json中添加以下内容:
{
    "name": "execute_amixer_command0",
    "uid": "root",
    "gid": "root"
}

特点

  • 优点:可以以root权限执行命令,适用于需要高权限的操作
  • 缺点:需要修改系统配置,适用于系统级应用开发

注意事项

  1. 权限问题

    • 应用层调用Shell命令可能受到权限限制
    • 某些命令需要特定权限才能执行
  2. 安全风险

    • 执行Shell命令存在安全风险,尤其是当命令参数来自用户输入时
    • 建议对输入参数进行严格验证
  3. 性能考虑

    • 频繁执行Shell命令可能影响应用性能
    • 建议合理控制命令执行频率
  4. 错误处理

    • 应妥善处理命令执行失败的情况
    • 对于popen方法,要确保正确关闭文件流
  5. 系统差异

    • 不同OpenHarmony版本可能存在差异
    • 请根据实际系统版本调整实现

总结

本文介绍了三种在OpenHarmony应用层调用Shell命令的方法:

  1. system()函数:适用于简单执行命令且不需要获取输出的场景
  2. popen()函数:适用于需要获取命令输出的场景
  3. 系统属性触发:适用于需要高权限执行命令的场景

开发者可以根据具体需求选择合适的方法。在使用过程中,请注意权限管理、安全防护和错误处理,确保应用的稳定性和安全性。
附件有笔者的测试用例源码供大家参考。

相关文件下载
shell_test.zip
6.02 MB
下载
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐