|
5 | 5 | import time |
6 | 6 | import logging |
7 | 7 | import threading |
| 8 | +import tempfile |
8 | 9 |
|
9 | | -from .typing import Cmd, RUsage |
| 10 | +from .typing import Cmd, RUsage, PathLike |
10 | 11 |
|
11 | 12 | logger = logging.getLogger(__name__) |
12 | 13 |
|
@@ -92,24 +93,40 @@ def _read_service_int_properties(name: str, properties: dict[str, Optional[int]] |
92 | 93 | def start_cmd( |
93 | 94 | name: str, cmd: Cmd, |
94 | 95 | setenv: dict[str, str] = {}, |
| 96 | + input: bytes = b'', |
| 97 | + logfile: Optional[PathLike] = None, |
95 | 98 | **kwargs: Any, # can't use P.kwargs here because there is no place for P.args |
96 | | -) -> subprocess.Popen: |
| 99 | +) -> None: |
| 100 | + if logfile is None: |
| 101 | + pid = os.getpid() |
| 102 | + output = f'/proc/{pid}/fd/1' |
| 103 | + else: |
| 104 | + output = str(logfile) |
| 105 | + |
97 | 106 | # don't use --collect here because it will be immediately collected when |
98 | 107 | # failed |
99 | 108 | cmd_s: Cmd = [ |
100 | | - 'systemd-run', '--pipe', '--quiet', '--user', |
101 | | - '--wait', '--remain-after-exit', '-u', name, |
| 109 | + 'systemd-run', '--quiet', '--user', '--remain-after-exit', |
| 110 | + '-u', name, |
102 | 111 | '-p', 'CPUWeight=100', '-p', 'KillMode=process', |
103 | 112 | '-p', 'KillSignal=INT', |
| 113 | + '-p', f'StandardOutput=append:{output}', |
| 114 | + '-p', f'StandardError=append:{output}', |
104 | 115 | ] |
105 | 116 |
|
106 | 117 | if cwd := kwargs.pop('cwd', None): |
107 | 118 | cmd_s += [f'--working-directory={str(cwd)}'] # type: ignore |
108 | 119 |
|
| 120 | + if input: |
| 121 | + fd, inputpath = tempfile.mkstemp(prefix='input-', suffix='.lilac') |
| 122 | + os.write(fd, input) |
| 123 | + os.close(fd) |
| 124 | + cmd_s += ['-p', f'StandardInput=file:{inputpath}'] # type: ignore |
| 125 | + |
109 | 126 | cmd_setenv = [f'--setenv={k}={v}' for k, v in setenv.items()] |
110 | 127 | cmd_s = cmd_s + cmd_setenv + ['--'] + cmd # type: ignore |
111 | 128 | logger.debug('running %s', subprocess.list2cmdline(cmd_s)) |
112 | | - return subprocess.Popen(cmd_s, **kwargs) |
| 129 | + subprocess.check_call(cmd_s, **kwargs) |
113 | 130 |
|
114 | 131 | def _get_service_info(name: str) -> tuple[int, str, str]: |
115 | 132 | '''return pid and control group path''' |
|
0 commit comments