Add Dosh server restart command
ci / test (push) Has been cancelled
ci / fuzz-smoke (push) Has been cancelled
ci / windows-client (push) Has been cancelled
ci / package-release (linux-x86_64, ubuntu-latest) (push) Has been cancelled
ci / package-release (macos-aarch64, macos-14) (push) Has been cancelled
ci / package-release (macos-x86_64, macos-13) (push) Has been cancelled
ci / package-release (windows-x86_64, windows-latest) (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
ci / test (push) Has been cancelled
ci / fuzz-smoke (push) Has been cancelled
ci / windows-client (push) Has been cancelled
ci / package-release (linux-x86_64, ubuntu-latest) (push) Has been cancelled
ci / package-release (macos-aarch64, macos-14) (push) Has been cancelled
ci / package-release (macos-x86_64, macos-13) (push) Has been cancelled
ci / package-release (windows-x86_64, windows-latest) (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
This commit is contained in:
+73
-15
@@ -216,6 +216,9 @@ async fn main() -> Result<()> {
|
||||
if matches!(args.server.as_deref(), Some("status" | "sessions")) {
|
||||
return run_status_command(&config, &args);
|
||||
}
|
||||
if args.server.as_deref() == Some("restart") {
|
||||
return run_restart_command(&config, &args);
|
||||
}
|
||||
if args.server.as_deref() == Some("forward") {
|
||||
args = rewrite_forward_command(args)?;
|
||||
}
|
||||
@@ -751,6 +754,29 @@ fn run_status_command(config: &dosh::config::ClientConfig, args: &Args) -> Resul
|
||||
)
|
||||
}
|
||||
|
||||
fn run_restart_command(config: &dosh::config::ClientConfig, args: &Args) -> Result<()> {
|
||||
if args.command.len() != 1 {
|
||||
return Err(anyhow!("usage: dosh restart <host>"));
|
||||
}
|
||||
let requested = args.command[0].clone();
|
||||
let hosts = load_hosts_config(None).unwrap_or_default();
|
||||
let host_config = hosts.hosts.get(&requested).cloned().unwrap_or_default();
|
||||
let server = status_ssh_target(&requested, &host_config);
|
||||
let ssh_port = args.ssh_port.or(host_config.ssh_port).or(config.ssh_port);
|
||||
println!("Restarting Dosh server for {requested}");
|
||||
if is_local_status_target(&server) {
|
||||
return run_local_script(RESTART_STATUS_SCRIPT, "restart local Dosh server");
|
||||
}
|
||||
run_remote_script(
|
||||
&server,
|
||||
ssh_port,
|
||||
args.ssh_key.as_deref(),
|
||||
args.ssh_known_hosts.as_deref(),
|
||||
RESTART_STATUS_SCRIPT,
|
||||
"restart remote Dosh server",
|
||||
)
|
||||
}
|
||||
|
||||
fn status_ssh_target(requested: &str, host_config: &dosh::config::HostConfig) -> String {
|
||||
let raw_server = host_config
|
||||
.ssh
|
||||
@@ -766,14 +792,20 @@ fn is_local_status_target(server: &str) -> bool {
|
||||
|
||||
const SESSIONS_STATUS_SCRIPT: &str = r#"printf 'tmux sessions:\n'; tmux ls 2>/dev/null || printf ' none\n'; printf '\nDosh service:\n'; systemctl --user --no-pager --plain status dosh-server.service 2>/dev/null | sed -n '1,8p' || pgrep -af dosh-server || printf ' not running\n'"#;
|
||||
|
||||
const RESTART_STATUS_SCRIPT: &str = r#"if command -v systemctl >/dev/null 2>&1 && systemctl --user list-unit-files dosh-server.service >/dev/null 2>&1; then systemctl --user restart dosh-server.service; else pkill -f 'dosh-server serve' 2>/dev/null || true; nohup "$HOME/.local/bin/dosh-server" serve >/tmp/dosh-server.log 2>&1 & fi; sleep 1; systemctl --user --no-pager --plain status dosh-server.service 2>/dev/null | sed -n '1,8p' || pgrep -af dosh-server || printf ' not running\n'"#;
|
||||
|
||||
fn run_local_sessions_command() -> Result<()> {
|
||||
run_local_script(SESSIONS_STATUS_SCRIPT, "run local status command")
|
||||
}
|
||||
|
||||
fn run_local_script(script: &str, context: &str) -> Result<()> {
|
||||
let status = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(SESSIONS_STATUS_SCRIPT)
|
||||
.arg(script)
|
||||
.status()
|
||||
.context("run local status command")?;
|
||||
.with_context(|| context.to_string())?;
|
||||
if !status.success() {
|
||||
return Err(anyhow!("local status command failed with status {status}"));
|
||||
return Err(anyhow!("{context} failed with status {status}"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1365,6 +1397,24 @@ fn run_sessions_command(
|
||||
ssh_port: Option<u16>,
|
||||
ssh_key: Option<&std::path::Path>,
|
||||
ssh_known_hosts: Option<&std::path::Path>,
|
||||
) -> Result<()> {
|
||||
run_remote_script(
|
||||
server,
|
||||
ssh_port,
|
||||
ssh_key,
|
||||
ssh_known_hosts,
|
||||
SESSIONS_STATUS_SCRIPT,
|
||||
"run remote status command",
|
||||
)
|
||||
}
|
||||
|
||||
fn run_remote_script(
|
||||
server: &str,
|
||||
ssh_port: Option<u16>,
|
||||
ssh_key: Option<&std::path::Path>,
|
||||
ssh_known_hosts: Option<&std::path::Path>,
|
||||
script: &str,
|
||||
context: &str,
|
||||
) -> Result<()> {
|
||||
let mut command = Command::new("ssh");
|
||||
if let Some(ssh_port) = ssh_port {
|
||||
@@ -1379,14 +1429,14 @@ fn run_sessions_command(
|
||||
.arg("-o")
|
||||
.arg(format!("UserKnownHostsFile={}", known_hosts.display()));
|
||||
}
|
||||
let remote_command = format!("sh -c {}", shell_word(SESSIONS_STATUS_SCRIPT));
|
||||
let remote_command = format!("sh -c {}", shell_word(script));
|
||||
let status = command
|
||||
.arg(server)
|
||||
.arg(remote_command)
|
||||
.status()
|
||||
.context("run remote sessions command")?;
|
||||
.with_context(|| context.to_string())?;
|
||||
if !status.success() {
|
||||
return Err(anyhow!("sessions command failed with status {status}"));
|
||||
return Err(anyhow!("{context} failed with status {status}"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -5044,15 +5094,16 @@ const TERMINAL_CLEANUP: &[u8] = concat!(
|
||||
mod tests {
|
||||
use super::{
|
||||
DisconnectStatus, DynamicForward, FrameBuffer, LocalForward, MAX_PENDING_USER_INPUT_BYTES,
|
||||
PredictMode, Predictor, RemoteForward, SshConfig, StatusAction, auth_allows, cache_key,
|
||||
cache_server_prefix, clear_cached_credentials, ensure_tui_safe_status_overlay,
|
||||
input_matches_escape, is_local_status_target, latest_release_download_url,
|
||||
load_first_native_identity_with_prompt, parse_dynamic_forward, parse_escape_key,
|
||||
parse_local_forward, parse_remote_forward, parse_ssh_config, queue_pending_user_input,
|
||||
raw_contains_host_table, recv_response_until, render_status_clear, render_status_overlay,
|
||||
requested_env, resolved_startup_command, rewrite_forward_command, selected_predict_mode,
|
||||
selected_udp_host, ssh_destination_host, ssh_username, ssh_with_user, startup_command,
|
||||
status_ssh_target, toml_bare_key_or_quoted, update_check_requested, valid_forward_host,
|
||||
PredictMode, Predictor, RESTART_STATUS_SCRIPT, RemoteForward, SshConfig, StatusAction,
|
||||
auth_allows, cache_key, cache_server_prefix, clear_cached_credentials,
|
||||
ensure_tui_safe_status_overlay, input_matches_escape, is_local_status_target,
|
||||
latest_release_download_url, load_first_native_identity_with_prompt, parse_dynamic_forward,
|
||||
parse_escape_key, parse_local_forward, parse_remote_forward, parse_ssh_config,
|
||||
queue_pending_user_input, raw_contains_host_table, recv_response_until,
|
||||
render_status_clear, render_status_overlay, requested_env, resolved_startup_command,
|
||||
rewrite_forward_command, selected_predict_mode, selected_udp_host, ssh_destination_host,
|
||||
ssh_username, ssh_with_user, startup_command, status_ssh_target, toml_bare_key_or_quoted,
|
||||
update_check_requested, valid_forward_host,
|
||||
};
|
||||
use dosh::config::{ClientConfig, CommandExtension, HostConfig};
|
||||
use dosh::native::EnvVar;
|
||||
@@ -5734,6 +5785,13 @@ mod tests {
|
||||
assert!(!is_local_status_target("server.example.com"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn restart_script_has_systemd_and_nohup_fallback() {
|
||||
assert!(RESTART_STATUS_SCRIPT.contains("systemctl --user restart dosh-server.service"));
|
||||
assert!(RESTART_STATUS_SCRIPT.contains("nohup"));
|
||||
assert!(RESTART_STATUS_SCRIPT.contains("dosh-server"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn release_download_url_uses_latest_release_asset() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user