How can I quit the bash when I acident run while with pipe - linux

I run the this command
$(while true;do echo Something && sleep 0.01; done;) | cat
Now I can not exit by Ctrl+C or background it by Ctrl+Z, and ps aux can't tell me which bash it is.How can I quit that bash ?
EDIT
I narrow donw the pid by find the cwd pgrep bash| (while read -r line; do lsof -p $line|grep cwd|grep EXPECTED_CWD && echo "GOT $line"; done;),finally kill that process.There is easier way to find that, but no /proc on mac.

Closing the terminal can help.
If you are using CLI-only os then you can switch to different terminal using Ctrl + Alt + F1 keys.
There you can use who or ps commands to get process-id and kill it.
ps -ef will list all processes.
you can kill second last bash process, as that will be the last command that you executed.
Note : process id assignment in linux is always greater than old one.

you're able to execute your commands with & symbol in the end of the command to run this command in background
In your case command looks like:
$(while true;do echo Something && sleep 0.01; done;) | cat &
It will show the process ID, and you'll be able to kill it, when you want

Related

How to wait for first rsync process to complete before running next command in shell/bash script

Below is the script I have. Basically I just want to copy files from the other server by calling out this script. Some files are large and what happens is that it will kill the first rsync command before it completes and proceed with the next. I tried to use screen command but I'm not sure how to code Ctrl+a d (to detach) in shell/bash.
HFDIR=/var/opt/ubkp/data/local/prework/hotfixes
RODIR=/var/opt/ubkp/data/local/prework/rollouts
THFDIR=$(ls -t /var/opt/ubkp/data/local | grep hotfix | head -1)
TRODIR=$(ls -t /var/opt/ubkp/data/local | grep rollout | grep -v check | head -1)
user=$(/usr/seos/bin/sewhoami)
if [ $user = "root" ]; then
echo "This script should not be run as the TRUE root user"
echo "Log in so that \"sewhoami\" does not display \"root\" and then execute this script."
exit
else
#list of ROs and HFs
list=/tmp/list.txt
echo -n "Enter Password: "
read -s PWD
# first rsync command
/usr/bin/expect<<EOD
spawn rsync -a $user#server:$HFDIR/* /var/opt/ubkp/data/local/$THFDIR
expect "assword"
send "$PWD\r"
wait $!
expect eof
EOD
# second rsync command
/usr/bin/expect<<EOD
spawn rsync -a $user#server:$RODIR/* /var/opt/ubkp/data/local/$TRODIR
expect "assword"
send "$PWD\r"
expect eof
EOD
fi
exit
Your second rsync will be killed after 10 seconds as that is the default timeout for expect eof. You should add a wait after the send, to wait forever until the process ends.
Also, your should remove the $! in the wait. It is a shell variable, not an expect variable. Fortunately in this case $! is empty because you have not run any commands in the shell in the background with &.

Killing a process based on nice value (bash)

I am currently doing an exercise that requires me to write a script that kills the "sleep" process based on the nice value of it. So in one terminal, a sleep command of 100 (with the default niceness value of 0) would be terminated immediately when I run my script in another terminal. However, I'm having trouble writing the script for it. Here is what I have so far:
#!/usr/local/bin/bash
nice="$(ps eo pid,user,nice,command | grep sleep)"
if nice <= 4
then
kill -9 sleep
fi
My question is: How do I get the nice value from a command into a simple variable that I can run through my if statement?
Also, I'm running into trouble running my scripts. When I have a sleep command run in one terminal, and try to input sh kill_sleep.sh, it insists that it can't open it. What could be going wrong?
The command below kills all sleep processes with niceness <= 4:
ps -o pid= -o nice= -C sleep | awk '$2<=4{system("kill " $1)}'
The option -C sleep tells ps to select only sleep commands.
The options -o pid= -o nice= specify that ps should output the process ID and the nice value while omitting the header.
In the awk command, $2<=4 selects only those lines that have nice less than or equal to 4. (Since nice is the second value on each line of ps output, awk refers to it as $2.)
For those selected lines, the awk command system("kill " $1) is run. This runs the shell command kill on the pid. (Since PID is the first value on each line of ps output, awk referes to it as $1.)
The kill pid command sends the process the default signal which is TERM. This signal allows the process to shut down properly. kill -9 should almost always be avoided.
You can also do it simply even without awk:
read pid nice < <(ps -C sleep ho pid,nice)
if (( $nice <= 4 ))
then kill $pid
fi
-C filters only sleep commands in ps output
h in ps -C sleep ho suppresses output of names of columns (header)
read assigns the according values to variables pid and nice
kill might be with -9 if you prefer
<(...) construct is process substitution, it allows to read from process output as if it was a file
If you want to reflect the possibility of several running sleep instances (and kill all which are not nice), you can read ps output in while loop:
while read pid nice; do
if (($nice <= 4))
then kill $pid;
fi
done < <(ps -C sleep ho pid,nice)
You can use awk to match one column and return another column:
sleep=$(ps eo pid,nice,command | awk '$3 == "sleep" && $2 <= 4 {print $1}')
if [ "$sleep" ]
then kill $sleep
fi

Bash: Using SSH to start a long-running remote command and collect its PID

When I do the following, then I have to press CTRL-c afterwards or the shell acts weird. Left/right arrows keys e.g. doesn't move correctly and the text is messed up.
# read -r pid < <(ssh 10.10.10.46 'sleep 50 & echo $!') ; echo $pid
2135
# Killed by signal 2.
^C
#
I need this for a script, so I'd like to know why CTRL-c is needed and is it possible to work around it?
Update
It looks like it opens an extra Bash shell, and that is the one that needs to be exited.
The command I am actually interesting in is
read -r pid < <(ssh 10.10.10.46 "mbuffer -4 -v 0 -q -I 8023 > /tmp/mtest & echo $!"); echo $pid
Try this instead:
read -r pid \
< <(ssh 10.10.10.46 'nohup mbuffer >/tmp/mtest </dev/null 2>/tmp/mtest.err & echo $!')
Three important changes:
Use of nohup (you could also get a similar effect with the bash built-in disown)
Redirection of stdin and stderr to files (preventing them from holding handles that connect, eventually, to your terminal).
Use of single quotes for the remote command (with double-quotes, expansions happen before ssh is started, so the $! you get is the PID of the most recently started local background process).

terminate infinite loop initiated in remote server when exiting bash script

Script which executes commands in infinite loop in background
<SOMETHING ELSE AT START OF SCRIPT>
cmd='while true;
do
ps aux | head;
sleep 1;
done > $FILE'
ssh root#$SERVER $cmd &
...
...
<SOME OTHER TASKS>
...
...
( at the end of this script, how to kill the above snippet executing in remote server)
[ kindly note i dont want to wait as the while loop is infinite ]
Read and tried some posts from stackoverflow, but could not find exact solution for this problem.
Rather than an infinite loop, use a sentinel file:
cmd='while [ -r /tmp/somefile];
do
# stuff
done > $FILE'
ssh root#$SERVER touch /tmp/somefile
ssh root#$SERVER $cmd &
# do other stuff
ssh root#$SERVER rm -f /tmp/somefile
This follows your current practice of putting the remote command in a variable, but the arguments against that cited elsewhere should be considered.
If you want to kill the ssh process running in background at the end of your script, just do:
kill $!
I assume this is the only (or the last) process you started in background.
Try following sequence
CTRL+Z
fg
CTRL+C
or
jobs
kill %jobspec
To kill everything belonging to user logged in you could try:
whois=`w|grep $user|awk '{print $2}'`;user=root; ssh $user#server -C "ps auwx|grep $whois|awk '{print \$2}'"
This will list all the processes owned by the user you just logged in as - just add |xargs kill -9
whois=`w|grep $user|awk '{print $2}'`;user=root; ssh $user#server -C "ps auwx|grep $whois|awk '{print \$2}'|xargs kill -9 "
whois=`w|grep $user|awk '{print $2}'`;user=root; ssh $user#server -C "ps auwx|grep $whois|awk '{print \$2}'|awk '{print "kill -9 " $1}'|/bin/sh "

Obtaining PID of Last Command Run on Other Machine

I am using the following code to launch a command on another machine:
#!/bin/bash
/usr/bin/rsh -n $Host_Name "cat asdf.txt &"
And I am trying to obtain the PID of the cat command by using the following:
/usr/bin/rsh -n $Host_Name pid="$!"
But when I echo $pid, it is just blank. What am I doing incorrectly? Is there an easier way of obtaining the PID of the last command that was executed on a different machine?
Thanks
You can only get the $! of the backgrounded command in the shell in which you started the command. If your command doesn't output anything to stderr, this could work:
/usr/bin/rsh -n $Host_Name "cat asdf.txt & echo $! >&2" 2> pidfile
The pid of the started command will then be stored locally in 'pidfile'.
Just a side-note: I would never use rsh. It is inherently insecure. I'd use ssh instead ;)

Resources