Compare commits
10
Commits
fd029a8ce2
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3e84d1257
|
||
|
|
36bd56bcc4
|
||
|
|
78ce7dac48
|
||
|
|
6b1d53f65d
|
||
|
|
c2b6eaa87a
|
||
|
|
953b9a791c
|
||
|
|
d6e0fd4025
|
||
|
|
5c5d2c4927
|
||
|
|
2a4ba5ed92
|
||
|
|
6cc86d7fdf |
@@ -0,0 +1,20 @@
|
||||
# Scripts
|
||||
|
||||
## tmux-sessionizer
|
||||
Inspired by [ThePrimeagen](https://github.com/ThePrimeagen/.dotfiles/blob/master/bin/.local/scripts/tmux-sessionizer), but in python
|
||||
|
||||
Create/load tmux session based on the path of a project, use fzf for selection
|
||||
|
||||
## tmux-ssh-group
|
||||
Open multiple ssh connection to multiple servers as sudo, can pass extra commands also.
|
||||
Will open a new window in tiled mode on all this servers at the same times
|
||||
|
||||
Read from config files located under `~/.ssh-tmux/`, with the format:
|
||||
```
|
||||
[Gestion controller]
|
||||
servers = myserver1.fqdn
|
||||
myserver2.fqdn
|
||||
myserver3.fqdn
|
||||
myserver4.fqdn
|
||||
commands = ls -l
|
||||
```
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
selected=`cat ~/.tmux-cht-languages ~/.tmux-cht-command | fzf`
|
||||
if [[ -z $selected ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
read -p "Enter Query: " query
|
||||
|
||||
if grep -qs "$selected" ~/.tmux-cht-languages; then
|
||||
query=`echo $query | tr ' ' '+'`
|
||||
tmux neww bash -c "echo \"curl cht.sh/$selected/$query/\" & curl cht.sh/$selected/$query & while [ : ]; do sleep 1; done"
|
||||
else
|
||||
tmux neww bash -c "curl -s cht.sh/$selected~$query | less"
|
||||
fi
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ $# -eq 1 ]]; then
|
||||
selected=$1
|
||||
else
|
||||
selected=$(find ~/Documents/Arcanite/ ~/Documents/PolyLAN/ ~/Documents/Python ~/Documents/ -mindepth 1 -maxdepth 1 -type d | fzf)
|
||||
fi
|
||||
|
||||
if [[ -z $selected ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
selected_name=$(basename "$selected" | tr . _)
|
||||
tmux_running=$(pgrep tmux)
|
||||
|
||||
if [[ -z $TMUX ]] && [[ -z $tmux_running ]]; then
|
||||
tmux new-session -s $selected_name -c $selected
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! tmux has-session -t=$selected_name 2> /dev/null; then
|
||||
tmux new-session -ds $selected_name -c $selected
|
||||
fi
|
||||
|
||||
tmux switch-client -t $selected_name
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import argparse
|
||||
import configparser
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from pyfzf.pyfzf import FzfPrompt
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--no-open",
|
||||
action="store_true",
|
||||
help="Do not open firefox window. Mostly for debugging",
|
||||
)
|
||||
parser_args = parser.parse_args()
|
||||
|
||||
|
||||
BASE_PATH = Path("~/.firefox/").expanduser()
|
||||
|
||||
configs = {}
|
||||
sections = {}
|
||||
for subconffile in os.listdir(BASE_PATH):
|
||||
if not subconffile.endswith(".ini"):
|
||||
continue
|
||||
|
||||
prefix = subconffile.replace(".ini", "").capitalize()
|
||||
config = configparser.ConfigParser()
|
||||
config.read(BASE_PATH / subconffile)
|
||||
|
||||
configs[subconffile] = config
|
||||
|
||||
for section in config.sections():
|
||||
section_name = f"[{prefix}] {section}"
|
||||
sections[section_name] = {
|
||||
"section": section,
|
||||
"config": subconffile,
|
||||
}
|
||||
|
||||
fzf = FzfPrompt()
|
||||
selections = fzf.prompt(
|
||||
["Select one or more group to open"] + list(sections.keys()),
|
||||
"--cycle --multi --header-lines 1",
|
||||
)
|
||||
|
||||
if not selections:
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
for selected_group in selections:
|
||||
info = sections[selected_group]
|
||||
config = configs[info["config"]]
|
||||
|
||||
prefix = config[info["section"]].get("prefix", "")
|
||||
suffix = config[info["section"]].get("suffix", "")
|
||||
|
||||
endpoints = [
|
||||
f"{prefix}{e}{suffix}" for e in config[info["section"]]["endpoints"].split("\n")
|
||||
]
|
||||
|
||||
data = ["firefox"]
|
||||
for endpoint in endpoints:
|
||||
data.extend(["--new-tab", endpoint])
|
||||
|
||||
subprocess.Popen(data)
|
||||
+35
-11
@@ -1,18 +1,29 @@
|
||||
import argparse
|
||||
import configparser
|
||||
import sys
|
||||
import time
|
||||
import libtmux
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import libtmux
|
||||
from pyfzf.pyfzf import FzfPrompt
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--servers-file", "-f", help="Servers file to connect to")
|
||||
parser_args = parser.parse_args()
|
||||
|
||||
if parser_args.servers_file:
|
||||
with open(parser_args.servers_file, "r") as file:
|
||||
data = file.read()
|
||||
|
||||
servers = []
|
||||
for line in data.strip().split("\n"):
|
||||
servers.append(line.strip())
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config_path = Path("~/.ssh-tmux-multi.ini").expanduser()
|
||||
config.read(config_path)
|
||||
|
||||
fav_key = "Favourite servers"
|
||||
|
||||
fzf = FzfPrompt()
|
||||
|
||||
|
||||
@@ -27,7 +38,9 @@ def get_all_known_ssh_hosts():
|
||||
servers.add(line.split(" ")[0])
|
||||
|
||||
# Check previous ssh command on histfile
|
||||
with open(Path("~/.histfile").expanduser(), "r", encoding="utf-8", errors="ignore") as file:
|
||||
with open(
|
||||
Path("~/.histfile").expanduser(), "r", encoding="utf-8", errors="ignore"
|
||||
) as file:
|
||||
lines = file.read().strip().split("\n")
|
||||
|
||||
for line in lines:
|
||||
@@ -47,14 +60,16 @@ def get_favourite_servers_first():
|
||||
|
||||
order = {}
|
||||
for server in servers:
|
||||
order[server] = '0'
|
||||
order[server] = "0"
|
||||
|
||||
for server, uses in config[fav_key].items():
|
||||
if server in order:
|
||||
order[server] = uses
|
||||
|
||||
# Return the most used servers first
|
||||
return [x[0] for x in sorted(order.items(), key=lambda x: int(x[1]), reverse=True)]
|
||||
for count, value in order.items():
|
||||
print(count, value)
|
||||
return [x[0] for x in sorted(order.items(), key=lambda x: x[1], reverse=True)]
|
||||
|
||||
|
||||
def write_choosen_servers(servers):
|
||||
@@ -68,12 +83,17 @@ def write_choosen_servers(servers):
|
||||
config[fav_key][server] = str(int(config[fav_key][server]) + 1)
|
||||
|
||||
else:
|
||||
config[fav_key][server] = '1'
|
||||
config[fav_key][server] = "1"
|
||||
|
||||
with open(config_path, "w") as file:
|
||||
config.write(file)
|
||||
|
||||
servers = fzf.prompt(get_favourite_servers_first(), "--cycle --multi --print-query")
|
||||
|
||||
if not parser_args.servers_file:
|
||||
servers = fzf.prompt(
|
||||
["Select server to connect to"] + get_favourite_servers_first(),
|
||||
"--cycle --multi --print-query --header-lines 1 --tmux center",
|
||||
)
|
||||
|
||||
# Strip from query if found else, use the query
|
||||
if len(servers) > 1:
|
||||
@@ -85,8 +105,10 @@ if not servers:
|
||||
write_choosen_servers(servers)
|
||||
|
||||
srv = libtmux.Server()
|
||||
active_session = srv.sessions.filter(session_attached='1')[0]
|
||||
window = active_session.new_window(f"ssh-multis {','.join(servers)}", window_shell=f"ssh {servers[0]}")
|
||||
active_session = srv.sessions.filter(session_attached="1")[0]
|
||||
window = active_session.new_window(
|
||||
f"ssh-multis {','.join(servers)}", window_shell=f"ssh {servers[0]}"
|
||||
)
|
||||
|
||||
for server in servers[1:]:
|
||||
window.select_layout("tiled")
|
||||
@@ -96,7 +118,9 @@ for server in servers[1:]:
|
||||
time.sleep(0.1)
|
||||
|
||||
# Confirm connection on asking panes
|
||||
confirmation_needed_text = "Are you sure you want to continue connecting (yes/no/[fingerprint])?"
|
||||
confirmation_needed_text = (
|
||||
"Are you sure you want to continue connecting (yes/no/[fingerprint])?"
|
||||
)
|
||||
for pane in window.panes:
|
||||
pane_content = pane.capture_pane()
|
||||
if pane_content and confirmation_needed_text == pane_content[-1]:
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import argparse
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from pprint import pprint
|
||||
|
||||
import libtmux
|
||||
import sh
|
||||
from pyfzf.pyfzf import FzfPrompt
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--no-open",
|
||||
action="store_true",
|
||||
help="Do not open tmux window. Mostly for debugging",
|
||||
)
|
||||
parser_args = parser.parse_args()
|
||||
|
||||
|
||||
# Get active tmux sessions
|
||||
srv = libtmux.Server()
|
||||
|
||||
fzf = FzfPrompt()
|
||||
commands = defaultdict(list)
|
||||
|
||||
all_tty = [p.pane_tty for p in srv.panes]
|
||||
|
||||
cmd = f"-t {' -t '.join(all_tty)} -o pid:10 -o tty:10 -o command -ww" # -f
|
||||
|
||||
sh_commands = sh.ps(cmd.split(" ")).stdout.decode().strip().split("\n")
|
||||
|
||||
# Ignore first lines (i.e: table headers)
|
||||
for cmd in sh_commands[1:]:
|
||||
pid = cmd[:10].strip()
|
||||
tty = cmd[10:20].strip()
|
||||
command = cmd[20:].strip()
|
||||
tty_number = int(tty.replace("pts/", ""))
|
||||
|
||||
if command in ["-zsh", "/bin/zsh"]:
|
||||
continue
|
||||
|
||||
commands[tty_number].append(
|
||||
{
|
||||
"pid": int(pid),
|
||||
"command": command,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def format_pane(pane):
|
||||
global commands
|
||||
|
||||
tty_number = int(pane.pane_tty.replace("/dev/pts/", ""))
|
||||
running_commands = sorted(commands[tty_number], key=lambda c: c["pid"])
|
||||
|
||||
if len(running_commands) >= 1:
|
||||
cmd = running_commands[0]
|
||||
|
||||
else:
|
||||
cmd = {"pid": "-", "command": "*command not found*"}
|
||||
|
||||
path = pane.pane_current_path.replace("/home/legrems/Documents/Arcanite", "~/D/A")
|
||||
path = path.replace("/home/legrems/Documents", "~/D")
|
||||
path = path.replace("/home/legrems", "~")
|
||||
return [
|
||||
f"{pane.pane_tty}: [{pane.session_name}: {pane.window_name}, {path}]: {cmd['command']}"
|
||||
]
|
||||
|
||||
|
||||
panes = []
|
||||
for pane in srv.panes:
|
||||
panes.extend(format_pane(pane))
|
||||
selections = fzf.prompt(
|
||||
["Select one pane you want to switch to"] + panes,
|
||||
"--cycle --header-lines 1 --tmux center",
|
||||
)
|
||||
|
||||
if not selections:
|
||||
sys.exit(0)
|
||||
|
||||
pane_name = selections[0]
|
||||
tty = pane_name.split(":")[0]
|
||||
|
||||
selected_pane = srv.panes.get(pane_tty=tty)
|
||||
|
||||
if parser_args.no_open:
|
||||
print(selected_pane)
|
||||
print(tty)
|
||||
tty_number = int(tty.replace("/dev/pts/", ""))
|
||||
pprint(commands[tty_number])
|
||||
|
||||
else:
|
||||
# Go to this session
|
||||
selected_pane.session.switch_client()
|
||||
|
||||
# Select the correct window
|
||||
selected_pane.window.select()
|
||||
|
||||
# And switch to this pane
|
||||
selected_pane.window.select_pane(selected_pane.pane_id)
|
||||
@@ -0,0 +1,31 @@
|
||||
import sys
|
||||
|
||||
import libtmux
|
||||
from pyfzf.pyfzf import FzfPrompt
|
||||
|
||||
# Get active tmux sessions
|
||||
srv = libtmux.Server()
|
||||
|
||||
fzf = FzfPrompt()
|
||||
|
||||
mapping = {}
|
||||
lm = max(len(s.name) for s in srv.sessions if s.name)
|
||||
for session in srv.sessions:
|
||||
string = f"({session.name: <{lm}}) {session.session_path}"
|
||||
mapping[string] = session
|
||||
|
||||
selections = fzf.prompt(
|
||||
["Select one session you want to switch to"] + list(mapping.keys()),
|
||||
"--cycle --header-lines 1 --tmux center",
|
||||
)
|
||||
|
||||
if not selections:
|
||||
sys.exit(0)
|
||||
|
||||
sess_str = selections[0]
|
||||
session = mapping[sess_str]
|
||||
session.switch_client()
|
||||
|
||||
session.active_window.active_pane.display_message(
|
||||
f"Switched to session: {session.name}"
|
||||
)
|
||||
@@ -0,0 +1,40 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import libtmux
|
||||
import sh
|
||||
from pyfzf.pyfzf import FzfPrompt
|
||||
|
||||
fzf = FzfPrompt()
|
||||
folders = [
|
||||
"~/Documents/Arcanite/",
|
||||
"~/Documents/PolyLAN/",
|
||||
"~/Documents/Python/",
|
||||
"~/Documents/",
|
||||
"~/Documents/Games/Minecraft/modded/",
|
||||
]
|
||||
|
||||
available_folders = (
|
||||
sh.find(
|
||||
*[Path(f).expanduser() for f in folders]
|
||||
+ "-mindepth 1 -maxdepth 1 -type d".split(" ")
|
||||
)
|
||||
.strip()
|
||||
.split("\n")
|
||||
)
|
||||
selected = fzf.prompt(
|
||||
["Select a folder to create or switch session to"] + available_folders,
|
||||
"--cycle --header-lines 1 --tmux center",
|
||||
)
|
||||
|
||||
if not selected:
|
||||
sys.exit(1)
|
||||
|
||||
selected = selected[0]
|
||||
session_name = selected.split("/")[-1]
|
||||
srv = libtmux.Server()
|
||||
|
||||
if not srv.has_session(session_name):
|
||||
srv.new_session(session_name, attach=False, start_directory=selected)
|
||||
|
||||
srv.switch_client(session_name)
|
||||
+117
-36
@@ -1,49 +1,95 @@
|
||||
import libtmux
|
||||
import argparse
|
||||
import configparser
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import libtmux
|
||||
from pyfzf.pyfzf import FzfPrompt
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--no-open",
|
||||
action="store_true",
|
||||
help="Do not open tmux window. Mostly for debugging",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--separate-sessions",
|
||||
"-s",
|
||||
action="store_true",
|
||||
help="Use a separate sessions for all of the groups",
|
||||
)
|
||||
parser_args = parser.parse_args()
|
||||
|
||||
|
||||
def get_window_name(session_name):
|
||||
name = session_name.replace("-", "").replace(" ", " ").replace(" ", "_")
|
||||
return f"{'' if parser_args.separate_sessions else 'ssh-multig '}{name}"
|
||||
|
||||
|
||||
BASE_PATH = Path("~/.ssh-tmux/").expanduser()
|
||||
|
||||
configs = {}
|
||||
sections = {}
|
||||
for subconffile in os.listdir(BASE_PATH):
|
||||
if not subconffile.endswith(".ini"):
|
||||
continue
|
||||
|
||||
prefix = subconffile.replace(".ini", "").capitalize()
|
||||
config = configparser.ConfigParser()
|
||||
config.read(BASE_PATH / subconffile)
|
||||
|
||||
configs[subconffile] = config
|
||||
|
||||
for section in config.sections():
|
||||
sections[section] = subconffile
|
||||
|
||||
section_name = f"[{prefix}] {section}"
|
||||
sections[section_name] = {
|
||||
"section": section,
|
||||
"config": subconffile,
|
||||
}
|
||||
|
||||
fzf = FzfPrompt()
|
||||
selected_group = fzf.prompt(sections.keys(), "--cycle")[0]
|
||||
selections = fzf.prompt(
|
||||
["Select one or more servers group to open"] + list(sections.keys()),
|
||||
"--cycle --multi --header-lines 1 --tmux center",
|
||||
)
|
||||
|
||||
config = configs[sections[selected_group]]
|
||||
|
||||
servers = config[selected_group]["servers"].split("\n")
|
||||
|
||||
extra_commands = []
|
||||
if "commands" in config[selected_group].keys():
|
||||
extra_commands = config[selected_group]["commands"].split("\n")
|
||||
|
||||
if not servers:
|
||||
sys.exit(1)
|
||||
if not selections:
|
||||
sys.exit(0)
|
||||
|
||||
# Get active tmux sessions
|
||||
srv = libtmux.Server()
|
||||
active_sessions = srv.sessions.filter(session_attached='1')
|
||||
active_sessions = srv.attached_sessions
|
||||
|
||||
if active_sessions:
|
||||
active_session = active_sessions[0]
|
||||
if parser_args.separate_sessions:
|
||||
sessions = srv.sessions.filter(name="SSH-MultiG")
|
||||
|
||||
if sessions:
|
||||
active_session = sessions[0]
|
||||
|
||||
else:
|
||||
active_session = srv.new_session(session_name="SSH-MultiG")
|
||||
|
||||
else:
|
||||
if len(active_sessions) > 1:
|
||||
session_choice = fzf.prompt(
|
||||
[
|
||||
"You have multiple active tmux sessions open. Choose one to create the window on"
|
||||
]
|
||||
+ [sess.name for sess in active_sessions],
|
||||
"--cycle --header-lines 1",
|
||||
)
|
||||
|
||||
if not session_choice:
|
||||
sys.exit(0)
|
||||
|
||||
active_session = srv.sessions.filter(name=session_choice[0])[0]
|
||||
|
||||
elif len(active_sessions) == 1:
|
||||
active_session = active_sessions[0]
|
||||
|
||||
else:
|
||||
raw_try = srv.cmd("display", "-p", "#{session_name}").stdout
|
||||
if raw_try:
|
||||
active_session = srv.sessions.filter(name=raw_try[0])[0]
|
||||
@@ -51,30 +97,65 @@ else:
|
||||
else:
|
||||
active_session = srv.sessions[0]
|
||||
|
||||
window = active_session.new_window(f"ssh-multig {','.join(servers)}", window_shell=f"ssh {servers[0]}")
|
||||
for selected_group in selections:
|
||||
|
||||
for server in servers[1:]:
|
||||
window.select_layout("tiled")
|
||||
info = sections[selected_group]
|
||||
config = configs[info["config"]]
|
||||
servers = config[info["section"]]["servers"].split("\n")
|
||||
|
||||
extra_commands = []
|
||||
if "commands" in config[info["section"]].keys():
|
||||
extra_commands = config[info["section"]]["commands"].split("\n")
|
||||
|
||||
if parser_args.no_open:
|
||||
print(selected_group)
|
||||
print(f" - Servers ({len(servers)}):")
|
||||
for server in servers:
|
||||
print(f" * {server}")
|
||||
|
||||
if extra_commands:
|
||||
print(f" - Extra commands ({len(extra_commands)}):")
|
||||
for command in extra_commands:
|
||||
print(f" * {command}")
|
||||
|
||||
continue
|
||||
|
||||
if not servers:
|
||||
continue
|
||||
|
||||
window_name = get_window_name(selected_group)
|
||||
if windows := active_session.windows.filter(name=window_name):
|
||||
windows[0].select()
|
||||
continue
|
||||
|
||||
window = active_session.new_window(window_name, window_shell=f"ssh {servers[0]}")
|
||||
|
||||
for server in servers[1:]:
|
||||
pane = window.split(shell=f"ssh {server}")
|
||||
# Select tiled layout each time, to ensure enough space
|
||||
window.select_layout("tiled")
|
||||
|
||||
# Wait until tmux finished working
|
||||
time.sleep(0.1)
|
||||
# Wait until tmux finished working
|
||||
time.sleep(0.05)
|
||||
|
||||
# Confirm connection on asking panes
|
||||
confirmation_needed_text = "Are you sure you want to continue connecting (yes/no/[fingerprint])?"
|
||||
for pane in window.panes:
|
||||
# Confirm connection on asking panes
|
||||
confirmation_needed_text = (
|
||||
"Are you sure you want to continue connecting (yes/no/[fingerprint])?"
|
||||
)
|
||||
for pane in window.panes:
|
||||
pane_content = pane.capture_pane()
|
||||
if pane_content and confirmation_needed_text == pane_content[-1]:
|
||||
pane.send_keys("yes")
|
||||
|
||||
window.set_window_option("synchronize-panes", "on")
|
||||
pane = window.panes[0]
|
||||
pane.send_keys("sudo su -")
|
||||
window.set_window_option("synchronize-panes", "on")
|
||||
pane = window.panes[0]
|
||||
pane.send_keys("sudo su -")
|
||||
|
||||
for command in extra_commands:
|
||||
for command in extra_commands:
|
||||
pane.send_keys(command)
|
||||
|
||||
window.set_window_option("synchronize-panes", "off")
|
||||
window.set_window_option("synchronize-panes", "off")
|
||||
window.select()
|
||||
window.select_layout("tiled")
|
||||
|
||||
window.select()
|
||||
srv.cmd("select-layout", "tiled")
|
||||
active_session.switch_client()
|
||||
|
||||
Reference in New Issue
Block a user