LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 05-07-2011, 04:37 AM   #1
r3sistance
Senior Member
 
Registered: Mar 2004
Location: UK
Distribution: CentOS 5.4, Mac OS 10.4 (tiger)
Posts: 1,005

Rep: Reputation: 79
BASH scripting, creating a custom service (CentOS)


I am trying to create a custom service to manage a minecraft server what runs in a screen session (this is to allow easy console access as opposed to running it as a nohup background process). I am hitting two main issues with this script so far and wondering if anybody is able to shed some light on it, considering I am far from the greatest BASH scripter on Earth.

The issues are related to start and stop. the first issue with start is there is a command run "screen -dmS minecraft java -Xms1024M -Xmx1024M -jar /minecraft/minecraft.jar nogui" what doesn't appear to work, however when run from console (copy and pasted) this command seems to run perfectly. I am uncertain as to why this is not working within the script. Also if run from a script in /minecraft it also appears to work but in the minecraftd script I have created at /etc/init.d it does not work. I think the issue might be related to the location but am not certain on it, nor how to resolve it.

the second issue with stop is that it works sometimes but at other times it does not, overall it seems to work about 30~50% of the time. When it works it passes a couple of disconnection messages to the screen session and then gives the stop command (the command to gracefully terminate the minecraft server). It seems to work more often when using screen that I attach to the minecraft session while it is running but really not sure if this is an issue with my scripting or an issue with how I am passing things to screen.

The full code in /etc/init.d/minecraftd is below

Code:
#!/bin/bash
## Script Information
## Script Author: Berwick East
## Script Version: --------
## Last Updated: 07-MAY-2011

## Note
## this script is only a free service management tool for minecraft and can be redistribed, Minecraft itself however is not as per copyrights
## (http://www.minecraft.net/copyright.jsp).

##http://it.megocollector.com/?p=805

SERVICE="Minecraft"
RETVAL=0
PROCESS=`ps aux | grep minecraft | egrep -v 'SCREEN|grep|etc/init.d|service'`

start()
{
        if [ -z "$PROCESS" ]
        then
                cd /minecraft
                service iptables restart > /dev/null
                echo "$SERVICE is being started"
                iptables -I RH-Firewall-1-INPUT -p tcp --dport 25565 -j ACCEPT
                screen -dmS minecraft java -Xms1024M -Xmx1024M -jar /minecraft/minecraft.jar nogui
        else
                echo "$SERVICE appears to already be running"
        fi
}

stop()
{
        if [ "$PROCESS" ]
        then
                echo "$SERVICE is now sending disconnection messages"
                screen -d minecraft > /dev/null
                echo "sending first disconnect message (60 seconds left)"
                screen -S minecraft -X stuff $'say Server is preparing to shutdown in 60 seconds please disconnect.\n'
                sleep 30
                echo "sending second disconnect message (30 seconds left)"
                screen -S minecraft -X stuff $'say Server will shutdown in 30 seconds, disconnect immediately.\n'
                sleep 20
                echo "sending final disconnect message (10 seconds left)"
                screen -S minecraft -X stuff $'say Server is about to shutdown, you will be automatically disconnected in 10 seconds.\n'
                screen -S minecraft -X stuff $'stop\n'
                service iptables restart > /dev/null
                echo "$SERVICE is now stopping"
                sleep 20
                RETEST=`ps aux | grep minecraft | egrep -v 'SCREEN|grep|etc/init.d|service'`
                if [ "$RETEST" ]
                then
                        echo "$SERVICE failed to stop in expected time, please enter 'screen -r minecraft' into the console and then enter 'STOP' manually."
                        exit 1
                else
                        echo "$SERVICE stopped successfully"
                fi
        else
                echo "$SERVICE not found, if running please kill manually"
                exit 1
        fi

}

status()
{
##http://www.anyexample.com/linux_bsd/bash/check_if_program_is_running_with_bash_shell_script.xml
        if [ "$PROCESS" ]
        then
            echo "$SERVICE is running"
        else
            echo "$SERVICE is stopped"
        fi

}

restart()
{
        if [ "$PROCESS" ]
        then
                stop
        else
                echo "$SERVICE was already stopped"
        fi

        start
}

case $1 in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit $RETVAL
Any help would be appreciated,
Thanks in advanced.

Last edited by r3sistance; 05-07-2011 at 04:42 AM.
 
Old 05-07-2011, 08:41 AM   #2
carltm
Member
 
Registered: Jan 2007
Location: Canton, MI
Distribution: CentOS, SuSE, Red Hat, Debian, etc.
Posts: 697

Rep: Reputation: 93
A couple of thoughts. Red Hat/Centos has it's own way of managing
services. To see a good example, look at /etc/init.d/crond. Notice
that it has several commented lines starting with the keyword chkconfig.
These are required to properly use the service management tools, ntsysv
and chkconfig. It's a good idea to start with this as a template and
update it to match your new service. It's more work, but it ensures
that your service will be compatible with the OS.

Second thought. I'll bet the issue with it not starting is that bash
knows whether or not it is being run interactively, and screen is
expecting to be run from an interactive shell. What's the difference?
In an interactive shell your keyboard is set up as input and output
goes to your display (unless redirected). In a non-interactive shell
there is no input and output is buffered (unless redirected). I hope
this makes sense.
 
Old 05-07-2011, 10:23 AM   #3
r3sistance
Senior Member
 
Registered: Mar 2004
Location: UK
Distribution: CentOS 5.4, Mac OS 10.4 (tiger)
Posts: 1,005

Original Poster
Rep: Reputation: 79
I'll look into configuring it to the template once I have things working (don't want it to be for nothing if I still can't get it working).

I am not sure I get the issue with interactive mode, I mean I can understand that when you run a script file it runs it in a separate shell, however in another script where I have copied and pasted the exact line from, it works fine, so I am not sure why it'd have that problem with one script file and not another. expect for testing I always start this process via script.
 
Old 05-07-2011, 01:08 PM   #4
carltm
Member
 
Registered: Jan 2007
Location: Canton, MI
Distribution: CentOS, SuSE, Red Hat, Debian, etc.
Posts: 697

Rep: Reputation: 93
When you start a shell interactively, it assumes that the input
is coming from a keyboard and output is going to a screen. When
it is started non-interactively (either in a startup script or
an at or cron job), it assumes there is no keyboard and that the
output is not being seen in real time by a human. So it's all
about input and output. Let me know if this still doesn't make
sense.

Some programs such as sudo check to see if the shell is interactive.
I'll bet that screen does such a check and it is refusing to run.

Try searching for "linux screen non-interactive shell" and see
if it sheds any light.
 
Old 05-07-2011, 01:16 PM   #5
carltm
Member
 
Registered: Jan 2007
Location: Canton, MI
Distribution: CentOS, SuSE, Red Hat, Debian, etc.
Posts: 697

Rep: Reputation: 93
Just to follow up on your last sentence. Any time you run a script
it starts in a shell (unless you use the . command). It's the parent
shell that is important here. When you type the command, the parent
shell is an interactive bash shell. When the command is run as a
service, the parent shell is a non-interactive shell launched by
the startup scripts.

Basically it's not a question of how the script was written, it's
a question of whether or not the invoking shell is interactive.

There may be a work around for this by adding some parameter to
screen. Try the search from my last reply.
 
Old 05-08-2011, 12:38 AM   #6
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,395
Blog Entries: 2

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
You can start screen without a controlling terminal, in detached mode. Then you have to use the '-X stuff' command to stuff characters into the detached session, and you can do that from your script, once you've launched screen. . I use this method quite a bit to start processes that have an interactive aspect to them, and to which I want to later attach and do interactive stuff.

--- rod.
 
Old 05-08-2011, 12:55 AM   #7
r3sistance
Senior Member
 
Registered: Mar 2004
Location: UK
Distribution: CentOS 5.4, Mac OS 10.4 (tiger)
Posts: 1,005

Original Poster
Rep: Reputation: 79
Thanks Carl,

I noticed this last night but had to go to sleep, I think I have a few ideas of where I need to look. Thank you.

theNbomr,

The Screen session already starts in detached mode, it uses -dmS and uses stuff already .
 
Old 05-08-2011, 06:24 AM   #8
r3sistance
Senior Member
 
Registered: Mar 2004
Location: UK
Distribution: CentOS 5.4, Mac OS 10.4 (tiger)
Posts: 1,005

Original Poster
Rep: Reputation: 79
Ok I have figured out all of my issues. Thank you carltm, while your suspicious appears to have been wrong you put me in the right mind set to figure this all out and I thank you for that!

I have figured out what is causing the stop issue and have resolved it dirtily. The screen session will only close if I have attached to it (via screen -r minecraft) either before or during the shut down, if I have never attached to the screen session it will not run, I have already found one thread on this and after reading this I had a brainstorm. From that I have figured out my own method, a second screen session that attaches to the first, this appears to work. The code now looks like

Code:
stop()
{
        if [ "$PROCESS" ]
        then
                screen -dms dirtyhack screen -r minecraft
                echo "$SERVICE is now sending disconnection messages"
                screen -d minecraft > /dev/null
                echo "sending first disconnect message (60 seconds left)"
                screen -S minecraft -X stuff $'say Server is preparing to shutdown in 60 seconds please disconnect.\n'
                sleep 30
                echo "sending second disconnect message (30 seconds left)"
                screen -S minecraft -X stuff $'say Server will shutdown in 30 seconds, disconnect immediately.\n'
                sleep 20
                echo "sending final disconnect message (10 seconds left)"
                screen -S minecraft -X stuff $'say Server is about to shutdown, you will be automatically disconnected in 10 seconds.\n'
                screen -S minecraft -X stuff $'stop\n'
                service iptables restart > /dev/null
                echo "$SERVICE is now stopping"
                sleep 20
                RETEST=`ps aux | grep minecraft | egrep -v 'SCREEN|grep|etc/init.d|service'`
                if [ "$RETEST" ]
                then
                        echo "$SERVICE failed to stop in expected time, please enter 'screen -r minecraft' into the console and then enter 'STOP' manually."
                        exit 1
                else
                        echo "$SERVICE stopped successfully"
                fi
        else
                echo "$SERVICE not found, if running please kill manually"
                exit 1
        fi

}
As for the start script, I never thought to try the script by doing "/etc/init.d/minecraftd start"! This method works so it very much appears that service is responsible for it not running. The problem can only be made more confusing however, the above stop routine also creates a screen session in very much the same way but this works fine by running service.

My suspicious became that service does not use the same path as the user that calls it and since when I installed java I only made the path for root I simpled switched "java" for the route to where java is actually held and that works. So this appears all solved, but if anybody has any cleaner way to handle the attach issue for the stop script I would like to hear it.

it appears Service has the path "/sbin:/usr/sbin:/bin:/usr/bin", what is definitely not the same as I have configure for root and thus my prolbem, Java does not exist in any of these, I will probably symbolic link java to /sbin now (probably crossing partitions but allows me to write the code a bit neater).

Last edited by r3sistance; 05-08-2011 at 06:55 AM. Reason: Service's Path
 
Old 05-08-2011, 07:42 AM   #9
carltm
Member
 
Registered: Jan 2007
Location: Canton, MI
Distribution: CentOS, SuSE, Red Hat, Debian, etc.
Posts: 697

Rep: Reputation: 93
Glad to hear that you've got it working.

There are many ways to handle paths. My suggestion would be
to export the path that you need from inside the startup
script. Doing it this way will prevent surprises later if
you install another instance of java or if a security update
makes some change to the default version of java. Just add
a line like this.

Code:
export PATH=$PATH:/path/to/java/bin:/any/other/required/path
 
Old 05-08-2011, 10:28 AM   #10
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,395
Blog Entries: 2

Rep: Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903Reputation: 903
You can probably get around the 'screen in screen' method by using the -p 0 option in your command that stuffs strings into the detached screen.
--- rod.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Creating a continuous 2cd custom installer using Centos? infernal211283_ Linux - General 5 04-01-2011 07:18 AM
[Bash] Creating service for a script. Problem with positional vars Mortuus Programming 1 05-10-2010 05:03 AM
Custom CentOS 5 Install with ks.cfg file and centOS all in one linux_newb Linux - Server 1 01-14-2010 06:13 PM
Creating custom headers to match a custom kernel utanja Debian 2 06-08-2007 03:15 PM
Bash scripting, mysql, and creating tables. hondaman Linux - General 2 09-25-2005 05:17 AM


All times are GMT -5. The time now is 06:34 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration