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 Thanks in advanced. |
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. |
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. |
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. |
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. |
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. |
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 :). |
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() 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). |
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 |
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. |
All times are GMT -5. The time now is 07:21 PM. |