mirror of
https://github.com/Cian-H/dotfiles.git
synced 2026-01-10 11:01:57 +00:00
Changed . token to _dot
This change allows the dotfiles to work with chezmoi (e.g: on windows) and improves grepability with neovim/telescope
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# Remoting
|
||||
This module provide convenient way to manage multiple remote clients.
|
||||
|
||||
## Prerequisites
|
||||
* Both `ssh` and `ssh script` require ssh to be installed on the host
|
||||
* `ssh script` requires nushell to be installed on the client
|
||||
* `ssh` can work both with and without nushell installed on the client however having it installed enables more sophisticated interaction between host and clients
|
||||
* `wake` requires wakeonlan to be installed on the host and clients to be configured to accept Wake on Lan magic packets
|
||||
|
||||
## `ssh` function
|
||||
This function serves as a wrapper around standard ssh command.
|
||||
|
||||
Function accepts following arguments:
|
||||
* name - Name of the client as specified in the config. This parameter is required (autocompletion enabled)
|
||||
* args - command to run on the client. If not provided ssh starts an interactive session with the client. If provided and specified client has nushell configured output will be returned as nushell table on the host allowing further parsing. If provided and specified client does not have nushell configured output will be passed back as is
|
||||
## `ssh script` function
|
||||
This function executes a nushell script on a client that has nushell configured.
|
||||
|
||||
Function accepts following arguments:
|
||||
* name - Name of the client as specified in the config. This parameter is required (autocompletion enabled)
|
||||
* script - Name of the script to be executed on the client. This parameter is required The script must be available in current scope in order to be used (autocompletion enabled)
|
||||
* args - Arguments to be passed to the script. Named parameters should be put in quotes to avoid parsing errors like this: `ssh script my-host my-script '--arg value'`
|
||||
|
||||
## `wake` function
|
||||
This function wakes specified clients via Wake on Lan.
|
||||
|
||||
Function accepts following arguments:
|
||||
* names - Name of clients to be woken up as specified in the config. (autocompletion enabled)
|
||||
|
||||
|
||||
## Config
|
||||
Client config is kept within (non-exported) `hosts` function as a list of records. Each record should contain following fields:
|
||||
|
||||
| Parameter | Is required? | Usage | Type |
|
||||
|-----------|----------------------------------------|------------------------------|--------|
|
||||
| name | Required | DNS name of the client | string |
|
||||
| domain | Either domain or IP must be specified | DNS domain of the client | string |
|
||||
| ip | Either domain or IP must be specified | IP address of the client | string |
|
||||
| username | Required | Username used for connection | string |
|
||||
| port | Required | SSH port | int |
|
||||
| mac | Required only for `wake` | MAC address of the client | string |
|
||||
| nu | Required | Whether nushell is installed | bool |
|
||||
|
||||
Example configuration records:
|
||||
* {name: 'host1', domain: 'nushell.sh', ip: '', username: 'username', port: 22, mac: 'AA:BB:CC:DD:EE;FF', nu: false}
|
||||
* {name: 'host2', domain: '', ip: '192.168.0.1', username: 'username', port: 2222, mac: '', nu: true}
|
||||
@@ -0,0 +1,98 @@
|
||||
# internal function that holds the host data. We could store it in a yaml file as well but that would require nushell to read it from disk every single time
|
||||
def hosts [] {
|
||||
[
|
||||
# Put your config here
|
||||
]
|
||||
}
|
||||
def "nu-complete wol" [] {
|
||||
hosts
|
||||
|where mac != ''
|
||||
|get name
|
||||
}
|
||||
|
||||
def "nu-complete nu" [] {
|
||||
hosts
|
||||
|where nu
|
||||
|get name
|
||||
}
|
||||
|
||||
def "nu-complete hosts" [] {
|
||||
hosts
|
||||
|get name
|
||||
}
|
||||
|
||||
def "nu-complete scripts" [] {
|
||||
scope commands
|
||||
|where is_custom
|
||||
|get -i command
|
||||
}
|
||||
|
||||
# Returns ssh connection as url to be consumed by original ssh command
|
||||
def get-url [
|
||||
host: record
|
||||
] {
|
||||
if 'ip' in ($host|columns) {
|
||||
echo $"ssh://($host.username)@($host.ip):($host.port)"
|
||||
} else {
|
||||
echo $"ssh://($host.username)@($host.name).($host.domain):($host.port)"
|
||||
}
|
||||
}
|
||||
|
||||
# Connect over ssh to one of predefined hosts, execute nushell commands and parse them on the host
|
||||
export def ssh [
|
||||
hostname: string@"nu-complete hosts" # name of the host you want to connect to
|
||||
...args # commands you wish to run on the host
|
||||
] {
|
||||
let host = (hosts|where name == $hostname|get -i 0)
|
||||
if ($host.nu) {
|
||||
if ($args|length) > 0 {
|
||||
^ssh (get-url $host) (build-string ($args|str join ' ') '|to json -r')|from json
|
||||
} else {
|
||||
^ssh (get-url $host)
|
||||
}
|
||||
} else {
|
||||
^ssh (get-url $host) $args
|
||||
}
|
||||
}
|
||||
|
||||
# Connect over ssh to one of predefined hosts, execute nushell script with arguments passed from the host
|
||||
export def "ssh script" [
|
||||
hostname: string@"nu-complete nu" # name of the host you want to connect to
|
||||
script: string@"nu-complete scripts" # name of the script
|
||||
...args # arguments you wish to pass to the script in key=value format
|
||||
] {
|
||||
let span = (metadata $script).span
|
||||
if $script in (scope commands|where is_custom|get command) {
|
||||
|
||||
let host = (hosts|where name == $hostname|get 0)
|
||||
let full_command = (build-string (view-source $script) '; ' $script ' ' ($args|str join ' ') '|to json -r')
|
||||
^ssh (get-url $host) ($full_command)|from json
|
||||
|
||||
} else {
|
||||
error make {
|
||||
msg: $"($script) is not a custom command, use regular ssh command instead"
|
||||
label: {
|
||||
text: "Not a custom command",
|
||||
start: $span.start,
|
||||
end: $span.end
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# Turns on specified hosts using Wake on Lan
|
||||
export def wake [
|
||||
...names: string@"nu-complete wol" # list of host names to wake
|
||||
] {
|
||||
hosts
|
||||
|where name in $names
|
||||
|each {|host|
|
||||
if $host.mac != '' {
|
||||
echo $"Waking ($host.name)"
|
||||
wakeonlan $host.mac|ignore
|
||||
} else {
|
||||
error make {
|
||||
msg: $"($host.name) does not support Wake on Lan"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
The `sockets` command returns a table containing information on network sockets and the processes they belong to.
|
||||
It is basically a join of the tables produced by the `lsof` command, and the nushell `ps` command.
|
||||
|
||||
<img width="1486" alt="image" src="https://user-images.githubusercontent.com/52205/196287615-00e46f8e-06ed-45ce-8fe7-a5c5f38afaaa.png">
|
||||
@@ -0,0 +1,32 @@
|
||||
export def sockets [--abbreviate-java-class-paths (-j)] {
|
||||
let input = (^lsof +c 0xFFFF -i -n -P)
|
||||
let header = ($input | lines
|
||||
| take 1
|
||||
| each { str downcase | str replace ' name$' ' name state' })
|
||||
let body = ($input | lines
|
||||
| skip 1
|
||||
| each { str replace '([^)])$' '$1 (NONE)' | str replace ' \((.+)\)$' ' $1' })
|
||||
[$header] | append $body
|
||||
| to text
|
||||
| detect columns
|
||||
| upsert 'pid' { |r| $r.pid | into int }
|
||||
| rename --column { name: connection }
|
||||
| reject 'command'
|
||||
| join-table (ps -l) 'pid' 'pid'
|
||||
| if $abbreviate_java_class_paths {
|
||||
upsert 'classpath' { |r| $r.command | java-cmd classpath }
|
||||
| upsert 'command' { |r| $r.command | java-cmd abbreviate-classpath }
|
||||
} else { $in }
|
||||
}
|
||||
|
||||
export def 'java-cmd classpath' [] {
|
||||
str replace '.* -classpath +(.+\.jar) +.*' '$1' | split row ':'
|
||||
}
|
||||
|
||||
export def 'java-cmd abbreviate-classpath' [] {
|
||||
str replace '[^ ]*\.jar' '*.jar'
|
||||
}
|
||||
|
||||
export def join-table [table: table, left_on: string, right_on: string] {
|
||||
dfr into df | join ($table | dfr into df) $left_on $right_on | dfr into nu
|
||||
}
|
||||
136
dot_config/nushell/nu_scripts/modules/network/ssh.nu
Normal file
136
dot_config/nushell/nu_scripts/modules/network/ssh.nu
Normal file
@@ -0,0 +1,136 @@
|
||||
export def ensure-cache [cache paths action] {
|
||||
mut cfgs = []
|
||||
for i in $paths {
|
||||
let cs = (do -i {ls ($i | into glob)})
|
||||
if ($cs | is-not-empty) {
|
||||
$cfgs = ($cfgs | append $cs)
|
||||
}
|
||||
}
|
||||
let cfgs = $cfgs
|
||||
let ts = ($cfgs | sort-by modified | reverse | get 0.modified)
|
||||
if ($ts | is-empty) { return false }
|
||||
let tc = (do -i { ls $cache | get 0.modified })
|
||||
if not (($cache | path exists) and ($ts < $tc)) {
|
||||
mkdir ($cache | path dirname)
|
||||
do $action | save -f $cache
|
||||
}
|
||||
open $cache
|
||||
}
|
||||
|
||||
export def 'str max-length' [] {
|
||||
$in | reduce -f 0 {|x, a|
|
||||
if ($x|is-empty) { return $a }
|
||||
let l = ($x | str length)
|
||||
if $l > $a { $l } else { $a }
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete ssh host" [] {
|
||||
rg -LNI '^Host [a-z0-9_\-\.]+' ~/.ssh | lines | each {|x| $x | split row ' '| get 1}
|
||||
}
|
||||
|
||||
export def parse-ssh-file [group] {
|
||||
$in
|
||||
| parse -r '(?<k>Host|HostName|User|Port|IdentityFile)\s+(?<v>.+)'
|
||||
| append { k: Host, v: null}
|
||||
| reduce -f { rst: [], item: {Host: null} } {|it, acc|
|
||||
if $it.k == 'Host' {
|
||||
$acc | upsert rst ($acc.rst | append $acc.item)
|
||||
| upsert item { Host : $it.v, HostName: null, Port: null, User: null, IdentityFile: null, Group: $group }
|
||||
} else {
|
||||
$acc | upsert item ($acc.item | upsert $it.k $it.v)
|
||||
}
|
||||
}
|
||||
| get rst
|
||||
| where {|x| not (($x.Host | is-empty) or $x.Host =~ '\*')}
|
||||
}
|
||||
|
||||
export def ssh-list [] {
|
||||
rg -L -l 'Host' ~/.ssh
|
||||
| lines
|
||||
| each {|x| cat $x | parse-ssh-file $x}
|
||||
| flatten
|
||||
}
|
||||
|
||||
def fmt-group [p] {
|
||||
$p | str replace $"($env.HOME)/.ssh/" ''
|
||||
}
|
||||
|
||||
def "ssh-hosts" [] {
|
||||
let cache = $'($env.HOME)/.cache/nu-complete/ssh.json'
|
||||
ensure-cache $cache [~/.ssh/config ~/.ssh/config*/* ] { ||
|
||||
let data = (ssh-list | each {|x|
|
||||
let uri = $"($x.User)@($x.HostName):($x.Port)"
|
||||
{
|
||||
value: $x.Host,
|
||||
uri: $uri,
|
||||
group: $"(fmt-group $x.Group)",
|
||||
identfile: $"($x.IdentityFile)",
|
||||
}
|
||||
})
|
||||
|
||||
let max = {
|
||||
value: ($data.value | str max-length),
|
||||
uri: ($data.uri | str max-length),
|
||||
group: ($data.group | str max-length),
|
||||
identfile: ($data.identfile | str max-length),
|
||||
}
|
||||
|
||||
{max: $max, completion: $data}
|
||||
}
|
||||
}
|
||||
|
||||
def "nu-complete ssh" [] {
|
||||
let data = (ssh-hosts)
|
||||
$data.completion
|
||||
| each { |x|
|
||||
let uri = ($x.uri | fill -a l -w $data.max.uri -c ' ')
|
||||
let group = ($x.group | fill -a l -w $data.max.group -c ' ')
|
||||
let id = ($x.identfile | fill -a l -w $data.max.identfile -c ' ')
|
||||
{value: $x.value, description: $"\t($uri) ($group) ($id)" }
|
||||
}
|
||||
}
|
||||
|
||||
export extern main [
|
||||
host: string@"nu-complete ssh" # host
|
||||
...cmd # cmd
|
||||
-v # verbose
|
||||
-i: string # key
|
||||
-p: int # port
|
||||
-N # n
|
||||
-T # t
|
||||
-L # l
|
||||
-R # r
|
||||
-D # d
|
||||
-J: string # j
|
||||
-W: string # w
|
||||
]
|
||||
|
||||
|
||||
def "nu-complete scp" [cmd: string, offset: int] {
|
||||
let argv = ($cmd | str substring ..$offset | split row ' ')
|
||||
let p = if ($argv | length) > 2 { $argv | get 2 } else { $argv | get 1 }
|
||||
let ssh = (ssh-hosts | get completion
|
||||
| each {|x| {value: $"($x.value):" description: $x.uri} }
|
||||
)
|
||||
let n = ($p | split row ':')
|
||||
if $"($n | get 0):" in ($ssh | get value) {
|
||||
^ssh ($n | get 0) $"sh -c 'ls -dp ($n | get 1)*'"
|
||||
| lines
|
||||
| each {|x| $"($n | get 0):($x)"}
|
||||
} else {
|
||||
let files = (do -i {
|
||||
ls -a ($"($p)*" | into glob)
|
||||
| each {|x| if $x.type == dir { $"($x.name)/"} else { $x.name }}
|
||||
})
|
||||
$files | append $ssh
|
||||
}
|
||||
}
|
||||
|
||||
export def --wrapped scp [
|
||||
lhs: string@"nu-complete scp",
|
||||
rhs: string@"nu-complete scp"
|
||||
...opts
|
||||
] {
|
||||
^scp -r ...$opts $lhs $rhs
|
||||
}
|
||||
Reference in New Issue
Block a user