find pid of ftp transfer in bash script - bash

I would like to get the pid of an ftp inside a bash script... running on solaris
this is my script:
#!/usr/bin/bash
...
ftp -inv $FTPDEST <<EOF
user $USER $PASS
put $file
EOF
I would like to get the pid of the ftp command so that i can after check if it is hung and kill it..
I had a server crash because there were about 200 ftp process open when an ftp was cutting the connection.. for some reason the ftp process remained open.
thank you
Mario

This is what you seem to describe but may not really be what you need. And this is a kind of hack....
#!/usr/bin/bash
trap 'exit 0' SIGUSR1 # this is the normal successful exit point
# trigger the trap if ftp in a background process completes before 10 seconds
(ftp -inv $FTPDEST <<-EOF 2>>logfile
user $USER $PASS
put $file
EOF
kill -s SIGUSR1 $PPID ) & # last line here shuts process down. and exits with success
childpid=$! # get the pid of the child running in background
sleep 10 # let it run 10 seconds
kill $childpid # kill off the ftp command, hope we get killed of first
wait
exit 1 # error exit ftp got hung up
Parent waits for 10 seconds while the ftp child completes in less than 10 seconds for a successful exit.
Success mean the child send a SIGUSR1 signal to the parent which then exits via the trap.
If the child takes too long, the parent kills off the slow ftp child and exits with error.

Related

How to run program in Bash script for as long as other program runs in parallel?

I have two programs server and client. server terminates after an unknown duration. I want to run client in parallel to server (both from the same Bash script) and terminate client automatically a few seconds after the server has terminated (on its own).
How can achieve this?
I can run multiple programs in parallel from a bash script and timeout a command in Bash without unnecessary delay, but I don’t know the execution duration of server beforehand so I can’t simply define a timeout for client. The script should continue running so exiting the script to kill the child processes is not an option.
Edits
This question only addresses waiting for both processes to terminate naturally, not how to kill the client process once the server process has terminated.
#tripleee pointed to this question on Unix SE in the comments, which works especially if the order of termination is irrelevant.
#!/bin/bash
execProgram(){
case $1 in
server)
sleep 5 & # <-- change "sleep 5" to your server command.
# use "&" for background process
SERVER_PID=$!
echo "server started with pid $SERVER_PID"
;;
client)
sleep 18 & # <-- change "sleep 18" to your client command
# use "&" for background process
CLIENT_PID=$!
echo "client started with pid $CLIENT_PID"
;;
esac
}
waitForServer(){
echo "waiting for server"
wait $SERVER_PID
echo "server prog is done"
}
terminateClient(){
echo "killing client pid $CLIENT_PID after 5 seconds"
sleep 5
kill -15 $CLIENT_PID >/dev/null 2>&1
wait $CLIENT_PID >/dev/null 2>&1
echo "client terminated"
}
execProgram server && execProgram client
waitForServer && terminateClient
With GNU Parallel you can do:
server() {
sleep 3
echo exit
}
client() {
forever echo client running
}
export -f server client
# Keep client running for 5000 ms more
# then send TERM and wait 1000 ms
# then send KILL
parallel -u --termseq 0,5000,TERM,1000,KILL,1 --halt now,success=1 ::: server client

Bash script run with timeout won't exit on SIGINT

I have a bash script which calls another bash script within a for loop (under a timeout condition) in the following format:
#!/bin/bash
trap 'trap - SIGTERM && kill 0' SIGINT SIGTERM EXIT
INNER_SCRIPT_PATH="./inner_script.sh"
for file in "$SAMPLEDIR"/*
do
if [[ "${file: -4}" == ".csv" ]]; then
CSVPATH="$file"
CSVNAME=${CSVPATH##*/} # extract file name
CSVNAME=${CSVNAME%.*} # remove extension
timeout -k 10s 30m bash "$INNER_SCRIPT_PATH"
fi
done
wait
Pressing Ctrl-C does not quit out of all the processes, and I have a feeling there is probably something wrong with the way I'm calling the inner bash script here (especially with timeout). Would appreciate feedback on how to make this better!
The issue is with the timeout command, that makes your script immune to Ctrl+C invocation. Since by default timeout runs in its own process group and not in the foreground process group, it is immune to the signals invoked from an interactive terminal.
You can run it with --foreground to accept signals from an interactive shell. See timeout Man page

How do I kill background processes / jobs started by a bash script after it finishes executing?

So I want to start a docker image, then a Django back-end and finally an angular front-end, let them run as long as I need to do tests/develop and then kill them when I'm done. To do this I first tried starting them all in a script and have them run in a background, and have a second script do kill %n for both processes. This doesn't work because the background processes are in another context, so the second script cannot reference them.
Then I tried this:
#!/bin/bash
# Exit Angular, Django and kill docker_img
function clean_up()
{
echo "Exiting..."
kill %2
kill %1
docker stop docker_img
reset
exit
}
# Trigger cleanup on CTRL + C
trap clean_up SIGINT
# Start docker database
docker start docker_img
# Start django backend
cd ~/Projects/DjangoBackend
source venv/bin/activate
python src/manage.py runserver &
sleep 3
echo 'Done starting django, starting angular'
sleep 1
# Start angular front end
cd ~/Projects/AngularFront
npm start &
However, after npm start & runs, the trap stops working, so it effectively becomes useless. I'm guessing it could be because once my script is done running the trap is no longer active, but I don't know how to fix this. What can I do?
If you are looking to kill a process in unix/linux, one way of doing it is you can record their PID in a file using ps -ef command.
And then use kill -9 to kill the process.
Example:
$ ps -ef | grep <process_name> | awk -F ' ' '{print $2}' > pid.txt
$ kill -9 `cat pid.txt`
ps -ef command will give all the running processes, using grep and process name, you can get PID of the particular process
awk is used to extract only PID from above command
kill -9 will forcefully kill the process
The answer seems to have been pretty easy, all I had to do was add wait to the end of the script, which allows the script to wait until the processes are done executing. Since two of the processes are servers, they don't stop unless prompted, so it'll just wait until SIGINT is received, at that point it'll run the clean_up function and exit gracefully.
Additionally, one could use the same trap but with the EXIT trigger instead of SIGINT to clean up when the script exits on it's own due to the processes closing.

How can I run a program until the user presses ctrl+c in bash?

I am trying to write a bash script in which I require to run a binary and if I press Ctrl+c then along with script, binary which is running in background should also be stopped. I am trying this code but it does not help:
#!/bin/bash
cd /usr/local/path-to-binary
./testBinary
read input
if (( "$input" == "Ctrl+c")); then
ps -aef|grep Binary
pkill -9 Binary
There a several errors in your script. Check the comments below your question.
Here is an example how to launch a background process and kill it on Ctrl+c:
#!/bin/bash
# Register signal handler for SIGINT (Ctrl+c)
trap abort INT
function abort() {
echo "Sending SIGINT to background process ${pid}"
# Kill background process
kill "${pid}"
# Wait for it to finish after killing it
wait "${pid}"
# Exit the script
echo "Aborting"
exit 1
}
# Start long running process in background (&)
sleep 1000 &
# Obtain the pid of that process
pid=$!
# Wait for the background process to finish
wait
PS: Just run the script and press Ctrl+c. read is not required.

BASH script suspend/continue a process within script

In my bash script I am writing, I am trying to start a process (sleep) in the background and then suspend it. Finally, the process with be finished. For some reason through, when I send the kill command with the stop signal, it just keeps running as if it received nothing. I can do this from the command line, but the bash script is not working as intended.
sleep 15&
pid=$!
kill -s STOP $pid
jobs
kill -s CONT $pid
You can make it work by enabling 'monitor mode' in your script: set -m
Please see why-cant-i-use-job-control-in-a-bash-script for further information

Resources