or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-execution.mdindex.mdprivilege-elevation.mdprocess-management.mdutilities.md

core-execution.mddocs/

0

# Core Command Execution

1

2

Primary command execution functionality providing a comprehensive interface for running shell commands with advanced timeout handling, encoding support, and flexible output redirection. This is the main entry point for command_runner functionality.

3

4

## Capabilities

5

6

### Main Command Execution

7

8

Executes shell commands with extensive configuration options for timeout handling, output capture, and cross-platform compatibility. Supports both synchronous and asynchronous execution patterns.

9

10

```python { .api }

11

def command_runner(

12

command, # Union[str, List[str]] - Command to execute

13

valid_exit_codes=False, # Union[List[int], bool] - Accepted exit codes

14

timeout=3600, # Optional[int] - Timeout in seconds (default: 3600)

15

shell=False, # bool - Use shell execution

16

encoding=None, # Optional[Union[str, bool]] - Output encoding

17

stdin=None, # Optional[Union[int, str, Callable, queue.Queue]]

18

stdout=None, # Optional[Union[int, str, Callable, queue.Queue]]

19

stderr=None, # Optional[Union[int, str, Callable, queue.Queue]]

20

no_close_queues=False, # Optional[bool] - Keep queues open after execution

21

windows_no_window=False, # bool - Hide console window on Windows

22

live_output=False, # bool - Display output during execution

23

method="monitor", # str - Capture method ("monitor" or "poller")

24

check_interval=0.05, # float - Polling interval in seconds

25

stop_on=None, # Callable - Custom stop condition function

26

on_exit=None, # Callable - Callback executed after completion

27

process_callback=None, # Callable - Callback with process information

28

split_streams=False, # bool - Return separate stdout/stderr tuples

29

silent=False, # bool - Suppress error logging

30

priority=None, # Union[int, str] - Process priority level

31

io_priority=None, # str - IO priority level

32

heartbeat=0, # int - Heartbeat logging interval (seconds)

33

**kwargs # Any - Additional subprocess.Popen arguments

34

):

35

"""

36

Execute shell commands with comprehensive error handling and output capture.

37

38

This function provides a robust interface for command execution that handles:

39

- Cross-platform command formatting and execution

40

- Reliable timeout enforcement with process tree termination

41

- Flexible output redirection (files, callbacks, queues, live display)

42

- Comprehensive encoding handling for different platforms

43

- Process priority and IO priority management

44

- Partial output capture on interruptions and timeouts

45

46

Args:

47

command: Command to execute. Can be string (shell=True) or list of strings.

48

String commands are automatically split on Unix when shell=False.

49

valid_exit_codes: Exit codes to treat as successful. False (default) means

50

only 0 is valid. True means any exit code is valid.

51

List means specific codes are valid.

52

timeout: Maximum execution time in seconds. None disables timeout.

53

shell: Whether to execute via shell. Required for complex shell commands.

54

encoding: Output encoding. None uses platform default (utf-8/cp437).

55

False returns raw bytes. String specifies custom encoding.

56

stdin: Input redirection. Can be subprocess constant, string filename,

57

callable function, or queue.Queue object.

58

stdout: Output redirection. None captures to return value, False discards,

59

string filename writes to file, callable sends to function,

60

queue.Queue sends to queue.

61

stderr: Error output redirection. Similar to stdout. None redirects to stdout.

62

no_close_queues: Keep queues open after execution (don't send None sentinel).

63

windows_no_window: Hide console window on Windows (Python 3.7+).

64

live_output: Show command output on screen during execution.

65

method: Capture method. "monitor" (default) uses lower CPU but limited features.

66

"poller" enables queues/callbacks and partial output on interrupts.

67

check_interval: Polling interval for timeout checks and output reading.

68

stop_on: Optional function returning bool to stop execution early.

69

on_exit: Optional callback function executed after command completion.

70

process_callback: Optional callback receiving subprocess.Popen object.

71

split_streams: Return (exit_code, stdout, stderr) instead of (exit_code, output).

72

silent: Suppress error logging (debug logs still shown).

73

priority: Process priority. String values: "verylow", "low", "normal", "high", "rt".

74

Unix also accepts int values -20 to 20.

75

io_priority: IO priority. String values: "low", "normal", "high".

76

heartbeat: Log heartbeat message every N seconds during execution.

77

**kwargs: Additional arguments passed to subprocess.Popen.

78

79

Returns:

80

Tuple[int, Optional[Union[bytes, str]]] - (exit_code, output) by default

81

Tuple[int, Optional[Union[bytes, str]], Optional[Union[bytes, str]]] -

82

(exit_code, stdout, stderr) when split_streams=True

83

84

Raises:

85

TimeoutExpired: When command exceeds timeout (converted to exit code -254)

86

InterruptGetOutput: Base class for output capture on interruptions

87

KbdInterruptGetOutput: On KeyboardInterrupt (converted to exit code -252)

88

StopOnInterrupt: When stop_on returns True (converted to exit code -251)

89

ValueError: For invalid arguments (converted to exit code -250)

90

91

Examples:

92

Basic usage:

93

>>> exit_code, output = command_runner('echo hello')

94

>>> print(exit_code, output.strip())

95

0 hello

96

97

With timeout:

98

>>> exit_code, output = command_runner('sleep 10', timeout=5)

99

>>> print(exit_code) # -254 for timeout

100

-254

101

102

Cross-platform ping:

103

>>> import os

104

>>> cmd = 'ping 127.0.0.1 -n 2' if os.name == 'nt' else ['ping', '-c', '2', '127.0.0.1']

105

>>> exit_code, output = command_runner(cmd)

106

107

File output:

108

>>> exit_code, _ = command_runner('ls -la', stdout='/tmp/output.txt')

109

110

Live output:

111

>>> exit_code, output = command_runner('ping 127.0.0.1', live_output=True)

112

113

Queue output (requires method="poller"):

114

>>> import queue

115

>>> q = queue.Queue()

116

>>> exit_code, _ = command_runner('ping 127.0.0.1', stdout=q, method='poller')

117

>>> # Read from queue in another thread

118

119

Custom stop condition:

120

>>> def should_stop():

121

... return some_condition_check()

122

>>> exit_code, output = command_runner('long_command', stop_on=should_stop)

123

"""

124

```

125

126

### Threaded Command Execution

127

128

Asynchronous version of command_runner that returns a Future object, enabling non-blocking command execution and integration with concurrent programming patterns.

129

130

```python { .api }

131

def command_runner_threaded(*args, **kwargs):

132

"""

133

Threaded version of command_runner returning concurrent.Future result.

134

135

Available only on Python 3.3+ due to concurrent.futures requirement.

136

Accepts the same arguments as command_runner but executes in a background

137

thread and returns immediately with a Future object.

138

139

Args:

140

*args: Same arguments as command_runner

141

**kwargs: Same keyword arguments as command_runner.

142

Special keyword '__no_threads=True' forces synchronous execution.

143

144

Returns:

145

concurrent.futures.Future: Future object containing the result.

146

Call .result() to get (exit_code, output) tuple

147

or .exception() to get any raised exceptions.

148

149

Examples:

150

Basic threaded execution:

151

>>> future = command_runner_threaded('ping 127.0.0.1')

152

>>> # Do other work while command runs

153

>>> exit_code, output = future.result() # Blocks until complete

154

155

With queue for live output:

156

>>> import queue

157

>>> output_queue = queue.Queue()

158

>>> future = command_runner_threaded('ping 127.0.0.1',

159

... stdout=output_queue, method='poller')

160

>>> # Read from queue while command runs

161

>>> while not future.done():

162

... try:

163

... line = output_queue.get(timeout=0.1)

164

... if line is None:

165

... break

166

... print(line, end='')

167

... except queue.Empty:

168

... pass

169

>>> exit_code, output = future.result()

170

171

Exception handling:

172

>>> future = command_runner_threaded('invalid_command')

173

>>> try:

174

... result = future.result()

175

... except Exception as e:

176

... print(f"Command failed: {e}")

177

"""

178

```

179

180

### Deferred Command Execution

181

182

Launches commands detached from the parent process with a specified delay. Useful for self-updating applications or cleanup operations that need to run after the parent process exits.

183

184

```python { .api }

185

def deferred_command(command, defer_time=300):

186

"""

187

Launch a detached command after a specified delay.

188

189

Creates an independent shell process that waits for the specified time

190

then executes the command. The command runs completely detached from

191

the parent process and will continue even if the parent exits.

192

193

Args:

194

command (str): Shell command to execute after delay

195

defer_time (int): Delay in seconds before execution (default: 300)

196

197

Returns:

198

None

199

200

Examples:

201

Auto-cleanup after 5 minutes:

202

>>> deferred_command('rm /tmp/tempfile.dat', defer_time=300)

203

204

Self-update scenario:

205

>>> deferred_command('cp /tmp/newversion.exe /app/myapp.exe', defer_time=10)

206

207

Log rotation:

208

>>> deferred_command('gzip /var/log/app.log', defer_time=3600)

209

"""

210

```

211

212

## Capture Methods

213

214

Command Runner supports two different output capture methods with different performance and feature characteristics:

215

216

### Monitor Method (Default)

217

218

- **Performance**: Lower CPU usage, fewer threads

219

- **Features**: Basic timeout and stop condition support

220

- **Limitations**: Cannot use queues/callbacks, limited partial output on interrupts

221

- **Best for**: Simple command execution with minimal resource usage

222

223

### Poller Method

224

225

- **Performance**: Slightly higher CPU usage, more threads

226

- **Features**: Full queue/callback support, complete partial output capture, live output

227

- **Capabilities**: Real-time output processing, interactive command support

228

- **Best for**: Advanced output handling, live monitoring, queue-based processing

229

230

## Output Redirection Options

231

232

Command Runner supports multiple output redirection patterns:

233

234

### Standard Capture (Default)

235

- `stdout=None`: Capture output in return value

236

- Returns complete output as string/bytes

237

238

### File Redirection

239

- `stdout="filename"`: Write output directly to file

240

- `stderr="filename"`: Write errors to separate file

241

- Files are opened in binary mode and written live

242

243

### Queue Redirection (Poller Method Only)

244

- `stdout=queue.Queue()`: Send output lines to queue

245

- Enables real-time processing in separate threads

246

- Queue receives None sentinel when complete

247

248

### Callback Redirection (Poller Method Only)

249

- `stdout=callback_function`: Call function with each output line

250

- Enables custom real-time processing logic

251

- Function called with string argument for each line

252

253

### Null Redirection

254

- `stdout=False`: Discard output (redirect to /dev/null or NUL)

255

- `stderr=False`: Discard error output

256

- Improves performance when output not needed

257

258

## Error Handling and Exit Codes

259

260

Command Runner provides comprehensive error handling with consistent exit codes:

261

262

### Standard Exit Codes

263

- `0`: Success (or any code in valid_exit_codes list)

264

- `> 0`: Command-specific error codes

265

266

### Special Exit Codes

267

- `-250`: Invalid arguments to command_runner

268

- `-251`: Custom stop_on function returned True

269

- `-252`: KeyboardInterrupt during execution

270

- `-253`: File not found or OS-level errors

271

- `-254`: Timeout expired

272

- `-255`: Unexpected exceptions

273

274

### Partial Output Recovery

275

Even when commands fail due to timeouts or interruptions, command_runner attempts to capture and return partial output, enabling debugging and recovery scenarios.