diff --git a/py-packages/sshtunnelier/sshtunnelier/__init__.py b/py-packages/sshtunnelier/sshtunnelier/__init__.py index 12ed7e7..0763a8c 100644 --- a/py-packages/sshtunnelier/sshtunnelier/__init__.py +++ b/py-packages/sshtunnelier/sshtunnelier/__init__.py @@ -11,7 +11,7 @@ from argparse import ArgumentError, ArgumentParser import psutil import yaml -__version__ = "2025.03.30" +__version__ = "2025.11.29" CONFDIR = os.path.expanduser("~/.config/ssh-tunnelier") CONF_OLD = os.path.join(CONFDIR, "tunnels.json") @@ -31,7 +31,7 @@ EXAMPLE_CONFIG = { "remote_port": 8080, "remote_address": "localhost", "reverse": False, - "comment": "`comment`, `reverse` and `remote_address` are not required", + "comment": "Only local_port and remote_port are required", } ], } @@ -50,6 +50,13 @@ def args(): nargs="?", help="Connection name to use", ) + parser.add_argument( + "--example", + dest="example", + default=False, + action="store_true", + help="Print example config and exit", + ) parser.add_argument( "--kill", dest="kill", @@ -76,7 +83,7 @@ def args(): default=None, action="store", type=str, - help="Instant tunnel. Syntax: sshserver:localport[:targethost][:remoteport][:options]", + help="Instant tunnel. Stays foreground. Syntax: sshserver:localport[:targethost][:remoteport][:options]", ) parser.add_argument( "--auto", @@ -85,6 +92,13 @@ def args(): action="store_true", help="Run all connections with auto-connect: true", ) + parser.add_argument( + "--fg", + dest="foreground", + default=False, + action="store_true", + help="Stay foreground.", + ) options = parser.parse_args() if options.name is None and options.connect is None and not options.auto: @@ -101,6 +115,8 @@ def check_type(d, key, expected, error_msg): if not isinstance(d[key], expected): raise ValueError(error_msg) +def print_example(): + yaml.dump(EXAMPLE_CONFIG, sys.stdout, sort_keys=False) def load_config(): """Load config, check types, add defaults""" @@ -115,7 +131,7 @@ def load_config(): else: print("Creating example config: " + CONF) with open(CONF, "w") as fp: - yaml.dump(EXAMPLE_CONFIG, fp) + yaml.dump(EXAMPLE_CONFIG, fp, sort_keys=False) with open(CONF, "r") as fp: config = yaml.safe_load(fp) @@ -171,6 +187,8 @@ def connect(name, config, foreground=False): else [] ) cmd = ["ssh", *f_commands, "-n", *options, *tunnels, host, remote_cmd] + if foreground: + list_connections(config, single=name) if not foreground: kill_connection(name, config) try: @@ -270,6 +288,9 @@ def parse_connect(connect_string): def main(): opts = args() config = load_config() + if opts.example: + print_example() + sys.exit(0) if opts.edit: config_edit(opts.edit) sys.exit(0) @@ -286,7 +307,7 @@ def main(): kill_connection(opts.name, config) sys.exit(0) if opts.name: - connect(opts.name, config) + connect(opts.name, config, foreground=opts.foreground) if __name__ == "__main__":