サーバープロセスや長時間の計算処理など、すぐに終了しないコマンドを管理する方法を解説します。
execute() ではなく spawn() を使用し、プロセスID(PID)の取得や状態管理を行います。
前提条件
プラグインのインストールが必要です。
npm run tauri add shell
Permissions (権限) の設定
src-tauri/capabilities/default.json に以下の権限を追加します。
{
"permissions": [
...,
"shell:allow-open",
{
"identifier": "shell:allow-execute",
"allow": [
{
"name": "python",
"cmd": "python",
"args": true
}
]
},
{
"identifier": "shell:allow-spawn",
"allow": [
{
"name": "python",
"cmd": "python",
"args": true
}
]
}
]
}
1. フロントエンドから作成する (TypeScript)
cmd.spawn() は Promise<Child> を返します。
Child オブジェクトを通じて、PID の取得や、プロセス終了時のハンドリングが可能になります。
import { Command, Child } from '@tauri-apps/plugin-shell';
let runningProcess: Child | null = null;
async function startServer() {
const cmd = Command.create('python', ['-m', 'http.server', '8080']);
// イベントリスナーの設定
cmd.on('close', () => {
console.log('Server stopped');
runningProcess = null;
});
cmd.on('error', err => console.error('Server error:', err));
cmd.stdout.on('data', line => console.log(`[SERVER]: ${line}`));
// プロセスの開始
runningProcess = await cmd.spawn();
console.log(`Server started with PID: ${runningProcess.pid}`);
}
2. バックエンドから作成する (Rust)
プロセスを維持管理するためには、tauri::State を使用して Child プロセスを保持する必要があります。
State の定義と登録 (lib.rs / main.rs)
use std::process::Child;
use std::sync::Mutex;
// プロセスを保持するための構造体
// この構造体を .manage() で登録し忘れると "state not managed" エラーになります
struct ProcessState(Mutex<Option<Child>>);
#[tauri::command]
fn start_server(state: tauri::State<'_, ProcessState>) -> Result<String, String> {
let mut lock = state.0.lock().unwrap();
if lock.is_some() {
return Err("Server already running".into());
}
// std::process::Command は権限設定なしで実行可能です(バックエンド側)
let child = std::process::Command::new("python")
.args(["-m", "http.server", "8080"])
.spawn()
.map_err(|e| e.to_string())?;
let pid = child.id();
*lock = Some(child);
Ok(format!("Started with PID: {}", pid))
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_shell::init()) // フロントエンドのサンプルを動作させるために必要
.manage(ProcessState(Mutex::new(None))) // ★重要: ここで State を初期化・登録します
.invoke_handler(tauri::generate_handler![start_server])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}