Linux: Read string from a file and execute commands in other scipt - linux

I'm a newbie to Linux/coding/scripting.
I currently have a script to start services of OBIEE application on RHEL 5.5.This is a sample from my script:
case "$1" in
start)
echo -e "Starting Node Manager..."
$ORACLE_FMW/wlserver_10.3/server/bin/startNodeManager.sh > startNodemanager.log 2>&1 &
sleep 30
echo -e "Starting Weblogic Server...."
$ORACLE_FMW/user_projects/domains/bifoundation_domain/bin/startWebLogic.sh > startWeblogic.log 2>&1 &
As you can see I'm trying to start 2 services one after the other using timeframe gap of 30seconds, independent of whether 1st service (Node Manager) starts or fails.
Instead of using static time gap in the script, I want to execute/start 2nd service(weblogic), based on output(of startNodemanager.log) from 1st service(NodeManager).
When NodeManager starts successfully, it ends its log file with certain string. EX:
"INFO: Secure socket listener started on port 9556"
So is it possible to write some command in my script (in place of time frame) that reads this string from output log and executes 2nd service only upon receiving desired string, till then holding off execution of 2nd service.
Thanks.
=======================
EDIT:
I have updated the script as suggested by yingted below.
It did not fix my issue yet. read is holding off triggering the 2nd service but it's failing to trigger it even after desired message is recorded in the log. My updated script looks like this using your command:
case "$1" in
start)
echo -e "Starting Node Manager..."
$ORACLE_FMW/wlserver_10.3/server/bin/startNodeManager.sh > startNodemanager.log 2>&1 &
read -r < <(tail -f startNodemanager.log | grep --line-buffered -Fx -- 'INFO: Secure socket listener started on port 9556')
echo -e "Starting Weblogic Server...."
$ORACLE_FMW/user_projects/domains/bifoundation_domain/bin/startWebLogic.sh > startWeblogic.log 2>&1 &
Problem might be with the message in the log.
Actually the message 'INFO: Secure socket listener started on port 9556' is preceded with a time stamp in the log.
Is there anyway I could add timestamp as wild card entry?

Your second process should follow the first one.
read -r < <(tail -f startNodemanager.log | grep --line-buffered 'INFO: Secure socket listener started on port 9556$')
The read command waits until startNodemanager.log contains a line ending in INFO: Secure socket listener started on port 9556.
read also accepts a -t timeout flag, which exits and sets $? greater than 128 if the timeout is exceeded. If it instead succeeds, read returns 0.

Related

Stop exec and telnet from showing login outputs

I have script that access module locally using the code
exec 3<> /dev/tcp/127.0.0.1/5037 ; echo -e "my command here" >&3 ; cat <&3
In the telnet session, I got the lines
Remote connection from 127.0.0.1:51698 to 127.0.0.1:5037
Closing connection to 127.0.0.1:51698
These outputs appears also with telnet sessions (without script)
How can I stop them as the script is running multiple timer per min and is spamming the console?
You can redirect it in a .txt file.
This might help you:
your_command > log.txt 2>&1
This will leave your console clean while all the logs will be saved on log.txt

Shell script to find out if a port is being listened to using netstat?

I have a server where a certain port (9999) is being listened to by a PHP socket server. What happens is that devices can connect to the socket and send messages. The code works fine right now, however, I noticed that the socket would sometimes close or die off, and I need to be able to put it back up online automatically without me having to log in and run it again.
What I'm thinking of is writing a Shell script that would check via netstat if there's a process running on port 9999, and if there's none, the script would trigger the PHP socket server to go online again. This Shell script would then be called by Cron every 1 or 2 minutes to check if the PHP socket is running.
I have bare minimum knowledge about Shell scripting, and so far, this was the only other thing I wrote in Shell:
#!/bin/sh
if pidof "my process name here" >/dev/null; then
echo "Process already running"
else
echo "Process NOT running!"
sh /fasterthancron.sh
fi
I think I should be able to reuse this code to some degree but I'm not sure what to replace the if condition with.
I have the idea that I'm supposed to use netstat -tulpn to figure out what processes are running, but I'm not sure how to filter through that list to find if a specific process is running on port 9999.
If you use netstat -tlpn (or its replacement ss -tpln), you can grep for 9999 and look for processes listening on it under "Local Address".
ss -tpln | awk '{ print $4 }' | grep ':9999'
Alternatively, if you can, use netcat or telnet instead e.g. nc -v localhost 9999.
if echo -n "\cD" | telnet ${host} ${port} 2>/dev/null; then
...
fi
I wrote something similar a while back: docker-wait
This was forked from aanand's docker-wait
You can use famous netstat -tupln with a simple if/else logic to do this.
if [ -z "$(sudo netstat -tupln | grep 9999)" ];
then
echo notinuse;
else
echo inuse;
fi

Why my named pipe input command line just hangs when it is called?

Why my named pipe input command line just hangs when it is called?
Based on the answers:
Writing to stdin of background process
Accessing bash command line args $# vs $*
Send command to a background process
Can I redirect output to a log file and background a process at the same time?
I wrote two shell scripts to communicate with my game server. And worked the first time I did it. Since it them they do not work anymore. Every time I do ./send.sh commands the command line hangs until I hit Ctrl+C.
It also hangs and does nothing when I do directly echo commamd > /tmp/srv-input
The scripts
It does start the server and configure it to read/receive my commands while it run in background:
start_czero_server.sh
#!/bin/sh
# Go to the game server application folder where the game application `hlds_run` is
cd /home/user/Half-Life
pkill -f hlds
# Set up a pipe named `/tmp/srv-input`
rm /tmp/srv-input
mkfifo /tmp/srv-input
cat > /tmp/srv-input &
echo $! > /tmp/srv-input-cat-pid
# Start the server reading from the pipe named `/tmp/srv-input`
# And also output all its console to the file `/home/user/Half-Life/my_logs.txt`
cat /tmp/srv-input | ./hlds_run -console -game czero +port 27015 > my_logs.txt 2>&1 &
# Successful execution
exit 0
This second script it just a wrapper which allow me easily to send commands to the my server:
send.sh
#!/bin/sh
echo "$#" > /tmp/srv-input
# Successful execution
exit 0
Now every time I want to send a command to my server I just do on the terminal:
./send.sh mp_timelimit 30
I always keep another open terminal open just to listen to my server server console. To do it just use the tail command with the -f flag to follow my server console output:
./tail -f /home/user/Half-Life/my_logs.txt
You would be better off just having hlds_run read directly from the pipe instead of having cat pipe it in.
Try
./hlds_run … > my_logs.txt 2>&1 < /tmp/srv-input &
Instead of
cat /tmp/srv-input | ./hlds_run …

Script to check connection every 5 minutes and write result to file (without ping) in LINUX

I need to check my connection to a spesific port every 5 minutes, currently i can't use ping command, so i need other alternative to do this.I want to execute this command in shell script
Can someone help me to show some example for this case?
port=80
ip=8.8.8.8
checkIntervalSecs=5
timeoutSecs=1
while true ; do
if $(nc -z -v -w$timeoutSecs $ip $port &>/dev/null); then
echo "Server is up!"
else
echo "Server is down!"
fi
sleep $checkIntervalSecs
done
This runs until you kill it. For an explanation of the nc command, it is basically taken from SO question #IporSircer suggested.

How to kill a process on no output for some period of time

I've written a program that is suppose to run for a long time and it outputs the progress to stdout, however, under some circumstances it begins to hang and the easiest thing to do is to restart it.
My question is: Is there a way to do something that would kill the process only if it had no output for a specific number of seconds?
I have started thinking about it, and the only thing that comes to mind is something like this:
./application > output.log &
tail -f output.log
then create script which would look at the date and time of the last modification on output.log and restart the whole thing.
But it looks very tedious, and i would hate to go through all that if there were an existing command for that.
As far as I know, there isn't a standard utility to do it, but a good start for a one-liner would be:
timeout=10; if [ -z "`find output.log -newermt #$[$(date +%s)-${timeout}]`" ]; then killall -TERM application; fi
At least, this will avoid the tedious part of coding a more complex script.
Some hints:
Using the find utility to compare the last modification date of the output.log file against a time reference.
The time reference is returned by date utility as the current time in seconds (+%s) since EPOCH (1970-01-01 UTC).
Using bash $[] operation to subtract the $timeout value (10 seconds on the example)
If no output is returned from the above find, then the file wasn't changed for more than 10 seconds. This will trigger a true in the if condition and the killall command will be executed.
You can also set an alias for that, using:
alias kill_application='timeout=10; if [ -z "`find output.log -newermt #$[$(date +%s)-${timeout}]`" ]; then killall -TERM application; fi';
And then use it whenever you want by just issuing the command kill_application
If you want to automatically restart the application without human intervention, you can install a crontab entry to run every minute or so and also issue the application restart command after the killall (Probably you may also want to change the -TERM to -KILL, just in case the application becomes unresponsive to handleable signals).
The inotifywait could help here, it efficiently waits for changes to files. The exit status can be checked to identify if the event (modify) occurred in the specified interval of time.
$ inotifywait -e modify -t 10 output.log
Setting up watches.
Watches established.
$ echo $?
2
Some related info from man:
OPTIONS
-e <event>, --event <event>
Listen for specific event(s) only.
-t <seconds>, --timeout <seconds>
Exit if an appropriate event has not occurred within <seconds> seconds.
EXIT STATUS
2 The -t option was used and an event did not occur in the specified interval of time.
EVENTS
modify A watched file or a file within a watched directory was written to.

Resources