mirror of
https://github.com/xxh/xxh
synced 2024-11-24 04:43:09 +00:00
commit
bd0cfa8b79
5 changed files with 130 additions and 9 deletions
15
README.md
15
README.md
|
@ -21,11 +21,24 @@ usage: xxh [ssh arguments] [user@]host[:port] [xxh arguments] ____
|
||||||
usage: xxh [-p SSH_PORT] [-l SSH_LOGIN] [-i SSH_PRIVATE_KEY] _____ / / __ \ \ / _/
|
usage: xxh [-p SSH_PORT] [-l SSH_LOGIN] [-i SSH_PRIVATE_KEY] _____ / / __ \ \ / _/
|
||||||
[-o SSH_OPTION -o ...] [+P PASSWORD] [+PP] ___ ( / / / \ \ /
|
[-o SSH_OPTION -o ...] [+P PASSWORD] [+PP] ___ ( / / / \ \ /
|
||||||
[user@]host[:port] \ \___/ / / /
|
[user@]host[:port] \ \___/ / / /
|
||||||
[+i] [+if] [+iff] [+v] [+vv] [+s SHELL] ____\ /__/ /
|
[+i] [+if] [+iff] [+hhr] [+v] [+vv] [+s SHELL] ____\ /__/ /
|
||||||
[+hh HOST_XXH_HOME] [+hf HOST_EXEC_FILE] [+hc HOST_EXEC_CMD] / \________/ /
|
[+hh HOST_XXH_HOME] [+hf HOST_EXEC_FILE] [+hc HOST_EXEC_CMD] / \________/ /
|
||||||
[+xc XXH_CONFIG] [+lh LOCAL_XXH_HOME] /____________________/
|
[+xc XXH_CONFIG] [+lh LOCAL_XXH_HOME] /____________________/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
There is `~/.xxh/.xxhc` config to save arguments and reuse it:
|
||||||
|
```
|
||||||
|
hosts:
|
||||||
|
myhost: # settings for myhost
|
||||||
|
-p: 2222 # set special port
|
||||||
|
|
||||||
|
"company-.*": # for all hosts by regex pattern
|
||||||
|
+if: # don't asking about install (++install-force)
|
||||||
|
+hhr: # remove after disconnect (++host-xxh-home-remove)
|
||||||
|
+hh: /tmp/.xxh # use special xxh home directory (++host-xxh-home)
|
||||||
|
```
|
||||||
|
The arguments will be automatically added when you run `xxh myhost` or `xxh company-server1`.
|
||||||
|
|
||||||
## Supported shells
|
## Supported shells
|
||||||
**[Xonsh shell](https://github.com/xxh/xxh-shell-xonsh-appimage)** — stable version with [pipeliner](https://github.com/xxh/xxh-plugin-xonsh-pipe-liner), [bar](https://github.com/xxh/xxh-plugin-xonsh-theme-bar), [autojump](https://github.com/xxh/xxh-plugin-xonsh-autojump) plugins.
|
**[Xonsh shell](https://github.com/xxh/xxh-shell-xonsh-appimage)** — stable version with [pipeliner](https://github.com/xxh/xxh-plugin-xonsh-pipe-liner), [bar](https://github.com/xxh/xxh-plugin-xonsh-theme-bar), [autojump](https://github.com/xxh/xxh-plugin-xonsh-autojump) plugins.
|
||||||
|
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -18,7 +18,7 @@ setuptools.setup(
|
||||||
'pyyaml'
|
'pyyaml'
|
||||||
],
|
],
|
||||||
platforms='Unix-like',
|
platforms='Unix-like',
|
||||||
scripts=['xxh'],
|
scripts=['xxh','xxhp'],
|
||||||
package_data={'xonssh_xxh':['*.xsh', '*.sh']},
|
package_data={'xonssh_xxh':['*.xsh', '*.sh']},
|
||||||
packages=setuptools.find_packages(),
|
packages=setuptools.find_packages(),
|
||||||
classifiers=[
|
classifiers=[
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
global_settings = {
|
global_settings = {
|
||||||
'XXH_VERSION': '0.4.5'
|
'XXH_VERSION': '0.4.6'
|
||||||
}
|
}
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
17
xxh
17
xxh
|
@ -38,16 +38,14 @@ class Xxh:
|
||||||
print(*args, file=sys.stderr, **kwargs)
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def snail(self):
|
def d2F0Y2ggLW4uMiB4eGggLWg(self):
|
||||||
try:
|
try:
|
||||||
terminal = os.get_terminal_size()
|
terminal = os.get_terminal_size()
|
||||||
terminal_cols = terminal.columns
|
terminal_cols = terminal.columns
|
||||||
except:
|
except:
|
||||||
terminal_cols=70
|
terminal_cols=70
|
||||||
|
|
||||||
if terminal_cols < 70:
|
if terminal_cols < 70:
|
||||||
return f"\n\nContribution: {self.url_xxh_github}\n\nPlugins: {self.url_xxh_plugins_search}"
|
return f"\n\nContribution: {self.url_xxh_github}\n\nPlugins: {self.url_xxh_plugins_search}"
|
||||||
|
|
||||||
l,r,s,t = (['@','-','_'][randint(0,2)], ['@','-','_'][randint(0,2)], ['_',' '][randint(0,1)], ['_',''][randint(0,1)])
|
l,r,s,t = (['@','-','_'][randint(0,2)], ['@','-','_'][randint(0,2)], ['_',' '][randint(0,1)], ['_',''][randint(0,1)])
|
||||||
return f"\n" \
|
return f"\n" \
|
||||||
+f" {s}___ __________ {l} {r}\n" \
|
+f" {s}___ __________ {l} {r}\n" \
|
||||||
|
@ -59,7 +57,7 @@ class Xxh:
|
||||||
+f"{' ' if not t else ''} _{t}__\\ /__/ / {self.url_xxh_plugins_search}\n" \
|
+f"{' ' if not t else ''} _{t}__\\ /__/ / {self.url_xxh_plugins_search}\n" \
|
||||||
+f"{' ' if not t else ''} / {'' if not t else ' '} \\________/ /\n" \
|
+f"{' ' if not t else ''} / {'' if not t else ' '} \\________/ /\n" \
|
||||||
+f"{' ' if not t else ''} /_{t}__________________/\n" \
|
+f"{' ' if not t else ''} /_{t}__________________/\n" \
|
||||||
+f"" # d2F0Y2ggLW4uMiB4eGggLWg
|
+f""
|
||||||
|
|
||||||
def pssh(self, cmd, accept_host=None, host_password=None, key_password=None):
|
def pssh(self, cmd, accept_host=None, host_password=None, key_password=None):
|
||||||
if self.password:
|
if self.password:
|
||||||
|
@ -264,7 +262,7 @@ class Xxh:
|
||||||
def main(self):
|
def main(self):
|
||||||
self.create_xxh_env()
|
self.create_xxh_env()
|
||||||
|
|
||||||
argp = argparse.ArgumentParser(description=f"Your favorite shell wherever you go through the ssh.\n{self.snail()}", formatter_class=RawTextHelpFormatter, prefix_chars='-+')
|
argp = argparse.ArgumentParser(description=f"Your favorite shell wherever you go through the ssh.\n{self.d2F0Y2ggLW4uMiB4eGggLWg()}", formatter_class=RawTextHelpFormatter, prefix_chars='-+')
|
||||||
argp.add_argument('--version', '-V', action='version', version=f"xonssh-xxh/{self.local_xxh_version}")
|
argp.add_argument('--version', '-V', action='version', version=f"xonssh-xxh/{self.local_xxh_version}")
|
||||||
argp.add_argument('-p', dest='ssh_port', help="Port to connect to on the remote host.")
|
argp.add_argument('-p', dest='ssh_port', help="Port to connect to on the remote host.")
|
||||||
argp.add_argument('-l', dest='ssh_login', help="Specifies the user to log in as on the remote machine.")
|
argp.add_argument('-l', dest='ssh_login', help="Specifies the user to log in as on the remote machine.")
|
||||||
|
@ -279,6 +277,7 @@ class Xxh:
|
||||||
argp.add_argument('+PP','++password-prompt', default=False, action='store_true', help="Enter password manually using prompt.")
|
argp.add_argument('+PP','++password-prompt', default=False, action='store_true', help="Enter password manually using prompt.")
|
||||||
argp.add_argument('+lh','++local-xxh-home', default=self.local_xxh_home, help=f"Local xxh home path. Default: {self.local_xxh_home}")
|
argp.add_argument('+lh','++local-xxh-home', default=self.local_xxh_home, help=f"Local xxh home path. Default: {self.local_xxh_home}")
|
||||||
argp.add_argument('+hh','++host-xxh-home', default=self.host_xxh_home, help=f"Host xxh home path. Default: {self.host_xxh_home}")
|
argp.add_argument('+hh','++host-xxh-home', default=self.host_xxh_home, help=f"Host xxh home path. Default: {self.host_xxh_home}")
|
||||||
|
argp.add_argument('+hhr','++host-xxh-home-remove', action='store_true', help=f"Remove xxh home on host after disconnect")
|
||||||
argp.add_argument('+hf','++host-execute-file', help=f"Execute script file placed on host and exit.")
|
argp.add_argument('+hf','++host-execute-file', help=f"Execute script file placed on host and exit.")
|
||||||
argp.add_argument('+hc','++host-execute-command', help=f"Execute command on host and exit.")
|
argp.add_argument('+hc','++host-execute-command', help=f"Execute command on host and exit.")
|
||||||
argp.add_argument('+s','++shell', default=self.shell, help="Xxh shell. Found: " + ', '.join(self.shells))
|
argp.add_argument('+s','++shell', default=self.shell, help="Xxh shell. Found: " + ', '.join(self.shells))
|
||||||
|
@ -290,7 +289,7 @@ class Xxh:
|
||||||
+ "usage: xxh [-p SSH_PORT] [-l SSH_LOGIN] [-i SSH_PRIVATE_KEY]\n" \
|
+ "usage: xxh [-p SSH_PORT] [-l SSH_LOGIN] [-i SSH_PRIVATE_KEY]\n" \
|
||||||
+ " [-o SSH_OPTION -o ...] [+P PASSWORD] [+PP]\n" \
|
+ " [-o SSH_OPTION -o ...] [+P PASSWORD] [+PP]\n" \
|
||||||
+ " [user@]host[:port]\n" \
|
+ " [user@]host[:port]\n" \
|
||||||
+ " [+i] [+if] [+iff] [+v] [+vv] [+s SHELL]\n" \
|
+ " [+i] [+if] [+iff] [+hhr] [+v] [+vv] [+s SHELL]\n" \
|
||||||
+ " [+hh HOST_XXH_HOME] [+hf HOST_EXEC_FILE] [+hc HOST_EXEC_CMD]\n" \
|
+ " [+hh HOST_XXH_HOME] [+hf HOST_EXEC_FILE] [+hc HOST_EXEC_CMD]\n" \
|
||||||
+ " [+xc CONFIG_FILE] [+lh LOCAL_XXH_HOME] [-h] [-V]\n"
|
+ " [+xc CONFIG_FILE] [+lh LOCAL_XXH_HOME] [-h] [-V]\n"
|
||||||
|
|
||||||
|
@ -552,6 +551,12 @@ class Xxh:
|
||||||
|
|
||||||
@(self.sshpass) ssh @(self.ssh_arg_v) @(self.ssh_arguments) @(host) -t bash @(str(host_xxh_home/'xxh/shells'/self.shell/'build/entrypoint.sh')) @(host_execute_file) @(host_execute_command) @(host_entrypoint_verbose)
|
@(self.sshpass) ssh @(self.ssh_arg_v) @(self.ssh_arguments) @(host) -t bash @(str(host_xxh_home/'xxh/shells'/self.shell/'build/entrypoint.sh')) @(host_execute_file) @(host_execute_command) @(host_entrypoint_verbose)
|
||||||
|
|
||||||
|
if opt.host_xxh_home_remove:
|
||||||
|
if self.verbose:
|
||||||
|
self.eprint(f'Remove {host}:{host_xxh_home}')
|
||||||
|
echo @(f"rm -rf {host_xxh_home}") | @(self.sshpass) ssh @(self.ssh_arg_v) @(self.ssh_arguments) @(host) -T "bash -s"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
self.eeprint(f"Windows is not supported. WSL1 is not recommended also. WSL2 is not tested yet.\nContribution: {self.url_xxh_github}")
|
self.eeprint(f"Windows is not supported. WSL1 is not recommended also. WSL2 is not tested yet.\nContribution: {self.url_xxh_github}")
|
||||||
|
|
103
xxhp
Executable file
103
xxhp
Executable file
|
@ -0,0 +1,103 @@
|
||||||
|
#!/usr/bin/env xonsh
|
||||||
|
import os, sys, argparse, re
|
||||||
|
from sys import exit
|
||||||
|
|
||||||
|
class XxhPackage(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.local_xxh_home_dir = p'~/.xxh'
|
||||||
|
self.quiet = False
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='xxhp is xxh package manager.',
|
||||||
|
usage='xxhp <command>\n\n'
|
||||||
|
+ ' install i Install xxh plugin or shell from https://github.com/xxh\n'
|
||||||
|
+ ' list l List of installed packages\n'
|
||||||
|
+ ' remove r Remove xxh plugin or shell\n\n'
|
||||||
|
+ 'Try `./xxhp <command> --help` to get more info.\n')
|
||||||
|
parser.add_argument('command', help='Command to run')
|
||||||
|
|
||||||
|
args = parser.parse_args(sys.argv[1:2])
|
||||||
|
if not hasattr(self, args.command):
|
||||||
|
print('Unrecognized command\n')
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
mkdir -p @(self.local_xxh_home_dir / 'xxh/shells') @(self.local_xxh_home_dir / 'xxh/plugins')
|
||||||
|
getattr(self, args.command)()
|
||||||
|
|
||||||
|
def eprint(self, *args, **kwargs):
|
||||||
|
if not self.quiet:
|
||||||
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
|
||||||
|
def eeprint(self, *args, **kwargs):
|
||||||
|
if not self.quiet:
|
||||||
|
print(*args, file=sys.stderr, **kwargs)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def i(self):
|
||||||
|
return self.install()
|
||||||
|
|
||||||
|
def install(self):
|
||||||
|
parser = argparse.ArgumentParser(description='')
|
||||||
|
parser.add_argument('package', help=f"xxh-package")
|
||||||
|
parser.add_argument('-v', '--verbose', action='store_true', help=f"Verbose mode")
|
||||||
|
parser.usage = parser.format_usage().replace('usage: xxhp ', 'xxhp install ')
|
||||||
|
opt = parser.parse_args(sys.argv[2:])
|
||||||
|
|
||||||
|
if not re.match('^[a-zA-Z-]+$', opt.package):
|
||||||
|
self.eeprint(f'Invalid package name: {opt.package}')
|
||||||
|
|
||||||
|
subdir = self.package_subdir(opt.package) or self.eeprint(f"Unknown package: {opt.package}")
|
||||||
|
|
||||||
|
package_git_url = f'https://github.com/xxh/{opt.package}'
|
||||||
|
|
||||||
|
self.eprint(f"Git clone {package_git_url}")
|
||||||
|
package_dir = self.local_xxh_home_dir/'xxh'/subdir/opt.package
|
||||||
|
r = ![git clone -q @(package_git_url) @(package_dir) 1>&2]
|
||||||
|
if r.returncode != 0:
|
||||||
|
self.eeprint(f'Git clone error')
|
||||||
|
|
||||||
|
self.eprint(f"Build {opt.package}")
|
||||||
|
@(package_dir/'build.xsh') 1>&2
|
||||||
|
self.eprint(f"Installed {opt.package}")
|
||||||
|
|
||||||
|
def r(self):
|
||||||
|
return self.remove()
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
parser = argparse.ArgumentParser(description='')
|
||||||
|
parser.add_argument('package', help=f"xxh-package")
|
||||||
|
parser.add_argument('-v', '--verbose', action='store_true', help=f"Verbose mode")
|
||||||
|
parser.usage = parser.format_usage().replace('usage: xxhp ', 'xxhp remove ')
|
||||||
|
opt = parser.parse_args(sys.argv[2:])
|
||||||
|
|
||||||
|
subdir = self.package_subdir(opt.package) or self.eeprint(f"Unknown package: {opt.package}")
|
||||||
|
package_dir = self.local_xxh_home_dir / 'xxh' / subdir / opt.package
|
||||||
|
if package_dir.exists():
|
||||||
|
rm -rf @(package_dir)
|
||||||
|
self.eprint(f"Removed {package_dir}")
|
||||||
|
else:
|
||||||
|
self.eeprint(f"Package not found: {package_dir}")
|
||||||
|
|
||||||
|
def l(self):
|
||||||
|
return self.list()
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
parser = argparse.ArgumentParser(description='')
|
||||||
|
parser.add_argument('-v', '--verbose', action='store_true', help=f"Verbose mode")
|
||||||
|
parser.usage = parser.format_usage().replace('usage: xxhp ', 'xxhp remove ')
|
||||||
|
opt = parser.parse_args(sys.argv[2:])
|
||||||
|
|
||||||
|
packages_dir = (self.local_xxh_home_dir / 'xxh').glob('**/xxh-*')
|
||||||
|
for p in sorted(packages_dir):
|
||||||
|
print(p.name)
|
||||||
|
|
||||||
|
def package_subdir(self, name):
|
||||||
|
if 'xxh-shell' in name:
|
||||||
|
return 'shells'
|
||||||
|
elif 'xxh-plugin' in name:
|
||||||
|
return 'plugins'
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
XxhPackage()
|
Loading…
Reference in a new issue