|  | 
| 7 | 7 | 
 | 
| 8 | 8 | # %% auto 0 | 
| 9 | 9 | __all__ = ['spark_chars', 'UNSET', 'walk', 'globtastic', 'maybe_open', 'mkdir', 'image_size', 'bunzip', 'loads', 'loads_multi', | 
| 10 |  | -           'dumps', 'untar_dir', 'repo_details', 'run', 'open_file', 'save_pickle', 'load_pickle', 'parse_env', | 
| 11 |  | -           'expand_wildcards', 'dict2obj', 'obj2dict', 'repr_dict', 'is_listy', 'mapped', 'IterLen', | 
| 12 |  | -           'ReindexCollection', 'SaveReturn', 'trim_wraps', 'save_iter', 'asave_iter', 'friendly_name', | 
|  | 10 | +           'dumps', 'untar_dir', 'repo_details', 'shell', 'ssh', 'rsync_multi', 'run', 'open_file', 'save_pickle', | 
|  | 11 | +           'load_pickle', 'parse_env', 'expand_wildcards', 'dict2obj', 'obj2dict', 'repr_dict', 'is_listy', 'mapped', | 
|  | 12 | +           'IterLen', 'ReindexCollection', 'SaveReturn', 'trim_wraps', 'save_iter', 'asave_iter', 'friendly_name', | 
| 13 | 13 |            'n_friendly_names', 'exec_eval', 'get_source_link', 'truncstr', 'sparkline', 'modify_exception', | 
| 14 | 14 |            'round_multiple', 'set_num_threads', 'join_path_file', 'autostart', 'EventTimer', 'stringfmt_names', | 
| 15 | 15 |            'PartialFormatter', 'partial_format', 'utc2local', 'local2utc', 'trace', 'modified_env', 'ContextManagers', | 
| @@ -198,6 +198,25 @@ def repo_details(url): | 
| 198 | 198 |     res = res.split(':')[-1] | 
| 199 | 199 |     return res.split('/')[-2:] | 
| 200 | 200 | 
 | 
|  | 201 | +# %% ../nbs/03_xtras.ipynb | 
|  | 202 | +def shell(*args, **kwargs): | 
|  | 203 | +    "Shortcut for `subprocess.run(shell=True)`" | 
|  | 204 | +    import subprocess | 
|  | 205 | +    return subprocess.run(*args, shell=True, **kwargs) | 
|  | 206 | + | 
|  | 207 | +# %% ../nbs/03_xtras.ipynb | 
|  | 208 | +def ssh(host, args='', user='ubuntu', sock=None): | 
|  | 209 | +    "Run SSH command with given arguments" | 
|  | 210 | +    sock_opts = f'-S {sock}' if sock else '' | 
|  | 211 | +    return shell(f'ssh {sock_opts} {args} {user}@{host}') | 
|  | 212 | + | 
|  | 213 | +# %% ../nbs/03_xtras.ipynb | 
|  | 214 | +def rsync_multi(ip, files, user='ubuntu', persist='5m'): | 
|  | 215 | +    "Transfer multiple files with rename using persistent SSH connection" | 
|  | 216 | +    sock = f'/tmp/ssh-{ip}-{user}' | 
|  | 217 | +    ssh(ip, f'-o ControlMaster=auto -o ControlPersist={persist} -N -f', user, sock) | 
|  | 218 | +    for src,dst in files: shell(f'rsync -az -e "ssh -S {sock}" {src} {user}@{ip}:{dst}') | 
|  | 219 | + | 
| 201 | 220 | # %% ../nbs/03_xtras.ipynb | 
| 202 | 221 | def run(cmd, *rest, same_in_win=False, ignore_ex=False, as_bytes=False, stderr=False): | 
| 203 | 222 |     "Pass `cmd` (splitting with `shlex` if string) to `subprocess.run`; return `stdout`; raise `IOError` if fails" | 
|  | 
0 commit comments