You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Tauri应用分场景调用带sudo的C函数并输出结果

解决方案:拆分权限场景,实现分级调用

针对你的需求,我们可以通过拆分C程序功能、新增Tauri命令、前端分级触发的方式实现默认看非sudo输出,输入密码后看全量输出的效果,具体步骤如下:

1. 改造C程序,支持参数控制执行范围

修改你的C程序,添加命令行参数区分执行模式:

  • 默认或传入--limited时,仅运行不需要sudo权限的函数
  • 传入--full时,运行全部函数(包括需要sudo的部分)

示例C代码片段:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 非sudo权限函数
void non_sudo_func() {
    printf("基础信息:系统当前用户为 %s\n", getenv("USER"));
}

// 需要sudo权限的函数
void sudo_required_func() {
    FILE *fp = fopen("/etc/shadow", "r");
    if (fp) {
        printf("敏感信息:成功读取系统用户密码文件\n");
        fclose(fp);
    } else {
        perror("获取敏感信息失败(需sudo权限)");
    }
}

int main(int argc, char *argv[]) {
    // 总是执行非sudo函数
    non_sudo_func();

    // 若传入--full参数,执行需要权限的函数
    if (argc > 1 && strcmp(argv[1], "--full") == 0) {
        sudo_required_func();
    }

    return 0;
}

2. 修改Tauri后端,新增分级调用命令

在src-tauri/src/lib.rs中添加两个命令,分别对应基础模式和全量模式,同时处理sudo密码的传递:

use std::process::Command;
use std::path::PathBuf;
use std::io::Write;
use tauri::command;

// 提取C程序路径获取逻辑,避免重复代码
fn get_c_program_path() -> PathBuf {
    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    path.pop();
    path.pop();
    path.push("backend");
    path.push("backend-c-file");
    path
}

// 提取命令输出处理逻辑
fn handle_output(output: std::process::Output) -> String {
    if output.status.success() {
        String::from_utf8_lossy(&output.stdout).to_string()
    } else {
        format!("执行错误:{}", String::from_utf8_lossy(&output.stderr))
    }
}

// 基础模式:仅运行非sudo函数
#[command]
fn run_c_limited() -> String {
    let c_path = get_c_program_path();
    match Command::new(&c_path).arg("--limited").output() {
        Ok(out) => handle_output(out),
        Err(e) => format!("启动程序失败:{}", e),
    }
}

// 全量模式:带sudo权限运行所有函数
#[command]
fn run_c_full(sudo_pwd: &str) -> String {
    let c_path = get_c_program_path();
    // 使用sudo -S从标准输入读取密码
    let mut cmd = Command::new("sudo")
        .arg("-S")
        .arg(&c_path)
        .arg("--full")
        .stdin(std::process::Stdio::piped())
        .spawn()
        .expect("启动sudo命令失败");

    // 将密码写入sudo的标准输入
    if let Some(mut stdin) = cmd.stdin.take() {
        let _ = writeln!(stdin, "{}", sudo_pwd);
    }

    // 等待命令执行完成并处理输出
    let output = cmd.wait_with_output().expect("获取sudo命令输出失败");
    handle_output(output)
}

3. 修改前端UI,实现分级触发逻辑

在src/App.jsx中添加基础调用按钮和密码输入区域,让用户可以按需切换模式:

import { useState } from 'react';
import { invoke } from '@tauri-apps/api/tauri';

function App() {
  const [output, setOutput] = useState("");
  const [sudoPwd, setSudoPwd] = useState("");
  const [showPwdInput, setShowPwdInput] = useState(false);

  // 触发基础模式调用
  const runLimited = async () => {
    const res = await invoke("run_c_limited");
    setOutput(res);
    setShowPwdInput(true);
  };

  // 输入密码后触发全量模式调用
  const runFull = async () => {
    const res = await invoke("run_c_full", { sudoPwd });
    setOutput(res);
  };

  return (
    <div style={{ padding: "20px" }}>
      <button onClick={runLimited}>查看基础信息</button>
      {showPwdInput && (
        <div style={{ marginTop: "10px" }}>
          <input
            type="password"
            placeholder="输入sudo密码"
            value={sudoPwd}
            onChange={(e) => setSudoPwd(e.target.value)}
          />
          <button onClick={runFull} style={{ marginLeft: "10px" }}>查看完整信息</button>
        </div>
      )}
      <pre style={{ marginTop: "20px", whiteSpace: "pre-wrap" }}>{output}</pre>
    </div>
  );
}

export default App;

注意事项

  • 安全性提示:使用echo传递密码可能会被系统进程列表或日志捕获,生产环境建议改用sudo -A配合Tauri实现的图形化密码弹窗(避免明文传递)。
  • 权限验证:可以在全量模式前先执行sudo -S true验证密码有效性,再执行C程序,提升用户体验。
  • C程序权限:确保编译后的C程序权限设置合理,避免被非授权用户滥用。

内容的提问来源于stack exchange,提问作者user27793975

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 06:43:11