setup --refresh-service: keep the launcher executable
systemd starts ~/.local/bin/anybot-run directly. install_systemd set 0755, the refresh path rewrote the file without it, and the unit then died with status=203/EXEC in a restart loop (seen on a Ubuntu hands box: service enabled, binary fresh, nothing running). One make_executable for both.
This commit is contained in:
parent
983a2c2f02
commit
7edc05ba9b
20
src/setup.rs
20
src/setup.rs
|
|
@ -42,6 +42,17 @@ fn write_atomic(path: &std::path::Path, body: String) -> std::io::Result<()> {
|
||||||
|
|
||||||
/// Quote a path for a systemd ExecStart line: a home folder with spaces (or a quote sign)
|
/// Quote a path for a systemd ExecStart line: a home folder with spaces (or a quote sign)
|
||||||
/// made the unit fail to start with no way to see why.
|
/// made the unit fail to start with no way to see why.
|
||||||
|
/// The launcher is started by systemd (`ExecStart=`) and by the terminal, so it must be executable.
|
||||||
|
fn make_executable(path: &std::path::Path) {
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
let _ = std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o755));
|
||||||
|
}
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
let _ = path;
|
||||||
|
}
|
||||||
|
|
||||||
fn systemd_quote(p: &std::path::Path) -> String {
|
fn systemd_quote(p: &std::path::Path) -> String {
|
||||||
let mut out = String::from("\"");
|
let mut out = String::from("\"");
|
||||||
for c in p.display().to_string().chars() {
|
for c in p.display().to_string().chars() {
|
||||||
|
|
@ -826,11 +837,7 @@ impl Plan {
|
||||||
std::fs::create_dir_all(&bin).map_err(|e| format!("建立 {} 失敗:{e}", bin.display()))?;
|
std::fs::create_dir_all(&bin).map_err(|e| format!("建立 {} 失敗:{e}", bin.display()))?;
|
||||||
let launcher = bin.join("anybot-run");
|
let launcher = bin.join("anybot-run");
|
||||||
write_atomic(&launcher, launcher_script(self.role, exe, &self.env)).map_err(|e| format!("寫入 {} 失敗:{e}", launcher.display()))?;
|
write_atomic(&launcher, launcher_script(self.role, exe, &self.env)).map_err(|e| format!("寫入 {} 失敗:{e}", launcher.display()))?;
|
||||||
#[cfg(unix)]
|
make_executable(&launcher);
|
||||||
{
|
|
||||||
use std::os::unix::fs::PermissionsExt;
|
|
||||||
let _ = std::fs::set_permissions(&launcher, std::fs::Permissions::from_mode(0o755));
|
|
||||||
}
|
|
||||||
let units = home.join(".config/systemd/user");
|
let units = home.join(".config/systemd/user");
|
||||||
std::fs::create_dir_all(&units).map_err(|e| e.to_string())?;
|
std::fs::create_dir_all(&units).map_err(|e| e.to_string())?;
|
||||||
// An older setup (deploy/linux/hands.sh) used another service name.
|
// An older setup (deploy/linux/hands.sh) used another service name.
|
||||||
|
|
@ -1004,6 +1011,9 @@ fn refresh_service() -> i32 {
|
||||||
eprintln!("✗ 寫入 {} 失敗:{e}", launcher.display());
|
eprintln!("✗ 寫入 {} 失敗:{e}", launcher.display());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
// systemd starts it directly: a launcher written without the execute bit fails the unit
|
||||||
|
// with status=203/EXEC and the service spins in a restart loop.
|
||||||
|
make_executable(&launcher);
|
||||||
match systemctl(&["restart", UNIT]) {
|
match systemctl(&["restart", UNIT]) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("已更新並重新啟動 AnyBot 服務。");
|
println!("已更新並重新啟動 AnyBot 服務。");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue