How to feed autocomplete data to a fish alias? - fish

I am starting with fish and one of the things I could not find in the extensive documentation was autocomplete feeds.
There is mention of Tab Completions in the tutorial but it addresses existing the existence of the mechanism itself, not its configuration.
I have a bunch of virtual machines I connect to via
machinectl shell <name of machine> /bin/bash
I could make alises for all my machines via
function cm
machinectl $argv shell /bin/bash;
end
but this requires to remember and type the machine name.
How could I use the output of machinectl list | tail -n +2 | head -n -2 | cut -f1 -d' ' as a feed/hint to my cm command so that it shows them when using Tab?
EDIT: I somehow missed this right at the top of the documentation: Tab completion (I found it after reviewing the answers)

This should get you off to a good start:
complete --command cm --no-files \
--arguments '(machinectl list | tail -n +2 | head -n -2 | cut -f1 -d" ")'
Entering that at the command line will activate it for the current session; to make it permanent add the line to a completions file as Kurtis describes (~/.config/fish/completions/cm.fish).

See help complete. You'll find the completions that ship with fish, including completions for ssh, in $__fish_datadir/completions. A completion you write for a private function or command would be placed in ~/.config/fish/completions/$cmd_name.fish

Related

follow logfile with tail and exec on event

i wonder if there is a more simplyfied way to run the tail -f or -F on a logfile and execute a command each time a special keyword is mentioned.
this is my working solution so far, but i don't like it for following reasons:
i have to write new lines for each match to log file to avoid endless loop
tail does not follow exactly the log, it could miss some lines while the command is executed
i am not aware about CPU usage because of high frequency
example:
#!/sbin/sh
while [ 1 ]
do
tail -n1 logfile.log | grep "some triggering text" && mount -v $stuff >> logfile.log
done
i tried the following but grep won't give return code until the pipe break
#!/sbin/sh
tail -f -n1 logfile.log | grep "some triggering text" && mount $stuff
i am running a script on android which is limited to
busybox ash
edit:
the problem is related to grep. grep won't give return code until the last line. what i need is return code for each line. maybe kind of a --follow option for grep, or sed, awk, or a user defined function which works with tail --follow

How can I make sure that the GNU linker ld is page aligning sections without a linker script?

As the title suggests, I'm trying to compile and subsequently link a binary, and I want the sections (text, data, bss, etc.) to be paged-aligned. To achieve that, I'm trying to pass the --no-omagicoption to ld. The literal command I'm using (in my Makefile) is:
ld --no-omagic -o build/initlink.out $^
ld --help says the option should have the following effect:
--no-omagic Page align data, make text readonly
But if I do an nm -n on the output, the first symbol in each section is not aligned. For example:
$ nm -n build/initlink.out | grep ' [tT] ' | head -n 1
00000000004000f0 T main
$ nm -n build/initlink.out | grep ' [dD] ' | head -n 1
00000000006d74b0 d vsscanf.basefix
$ nm -n build/initlink.out | grep ' [bB] ' | head -n 1
00000000006e7200 B __bss_start
If it's important, one thing with which I'm trying to link is a static library (.a extension).
Is there anything that I could be doing wrong? Is there another way to ensure page alignment of sections, without resorting to a linker script? I've tried using the --section-alignment option, but when I do, I'm told that it's unrecognized. The static library defines some strange symbols (involving "linker sets," which I've found to be woefully undocumented) with which I was running into issues, so I want to try to do this without having to do anything but tell the linker to put sections in certain places.

Using xargs arguments twice

I need to check if local file is same as remote host file.
The file locations are like below:
File1 at Local machine
./remotehostname/home/a/b/scripts/xyz.cpp
File2 at remote machine
remotehostname:/home/a/b/scripts/xyz.cpp
I intend to compare these 2 files, using the command
diff ./remotehostname/home/a/b/scripts/xyz.cpp remotehostname:/home/a/b/scripts/xyz.cpp
find . -type f | grep -v .svn |xargs -I % diff %
I need to change % to take remotehost and compare the file.
Not sure how to apply sed on %. Or is there a better way to compare such files.
One way could be to save the list of files and then apply sed on that file, but I think there should be an even better way. Also the diff doesnt work on remote hosts, maybe I need to use output of dry rsync?
This can be done with xargs, but I prefer to use while read in bash.
xargs method
find . -type f | grep -v .svn | sed 's/.*/& remotehostname:&/' | xargs -n2 diff
The sed command duplicates the input and makes whatever modifications you need. The xargs then passes the inputs to diff two at a time. This will not work if any filename contain spaces.
bash method
find . -type f | grep -v .svn | while read line; do
diff "$line" "remotehostname:$line"
done
The bash read command reads a line from stdin, places it in the name variable, $line, and returns true. You can then put whatever you like inside the loop, so you get total freedom to rewrite the filename however you need. When the input runs out, read returns false, and the loop exits.
Note that piping things into loops has some interesting side effects that are not relevant here, but might bite you one day.
If you are interested in the actual difference (and not just whether they differ - which rsync is brilliant for telling you) then you can do this using GNU Parallel:
find . -type f | grep -v .svn |
parallel diff {} '<(ssh {= s:./::;s:/.*:: =} cat {= s:([^/]+/){2,2}::;$_=::shell_quote_scalar($_) =})'
s:./::;s:/.*:: = hostname from path
s:([^/]+/){2,2}:: = rest of path
::shell_quote_scalar = \-quote special chars as needed by the shell
GNU Parallel is a general parallelizer and makes is easy to run jobs in parallel on the same machine or on multiple machines you have ssh access to. It can often replace a for loop.
If you have 32 different jobs you want to run on 4 CPUs, a straight forward way to parallelize is to run 8 jobs on each CPU:
GNU Parallel instead spawns a new process when one finishes - keeping the CPUs active and thus saving time:
Installation
If GNU Parallel is not packaged for your distribution, you can do a personal installation, which does not require root access. It can be done in 10 seconds by doing this:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
For other installation options see http://git.savannah.gnu.org/cgit/parallel.git/tree/README
Learn more
See more examples: http://www.gnu.org/software/parallel/man.html
Watch the intro videos: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Walk through the tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html
Sign up for the email list to get support: https://lists.gnu.org/mailman/listinfo/parallel

Executing perl script inside bash script

I inherited a long bash script that I recently needed to modify. The bash script is run as a cronjob on a daily basis. I am decent with bash scripting, but I do not know much about Perl.
I had to substitute all "rm" commands with a call to a perl script that does something similar (for security purposes). This script was not written by me, so there is no -f flag to skip the confirmation prompt. Therefore, to automate this script I pipe "yes" to the script.
Here is an example where I am sequentially deleting two directories:
echo REMOVING FILES TO SAVE DISK SPACE
echo "yes | sudo nice -n -10 perl <path_to_delete_script.pl> -dir <del_dir1>"
yes | sudo nice -n -10 perl <path_to_delete_script.pl> -dir <del_dir1>
echo "yes | sudo nice -n -10 perl <path_to_delete_script.pl> -dir <del_dir2>"
yes | sudo nice -n -10 perl <path_to_delete_script.pl> -dir <del_dir2>
echo DONE.
In my output file, I see the following:
REMOVING FILES TO SAVE DISK SPACE
yes | sudo nice -n -10 perl <path_to_delete_script.pl> -dir <del_dir1>
yes | sudo nice -n -10 perl <path_to_delete_script.pl> -dir <del_dir2>
DONE.
It does not appear that the perl script has run. Yet when I copy and paste those two commands into the terminal, they both run fine.
Any help is appreciated. Thank you in advance.
You simply put do
yes | ./myscript.pl
Thanks for all the comments. I ended up changing the group and permissions of the tool and all output files. This allowed me to run the perl script without using "sudo," which others pointed out is bad practice.

Simple Terminal Command Question - Is there a command to pull a certain line out of an input?

I have a simple question. Is there a command that allows you to pull a certain line out of an input? Like if I wanted the 7th line from ifconfig. Is there a way to do this: ifconfig | [command] 7?
Thanks!
YOu can use sed to extract a particular line from a file and/or from standard in as follows
sed -n '7p' filename or
some_command | sed -n '7p'
This should do it
ifconfig | head -n 7 | tail -n 1