Register FAQ / Rules Forum Spy Search Today's Posts Mark Forums Read
Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Apr 29, 2011, 04:34 AM   #1
sivaprakash
macrumors member
 
Join Date: Mar 2011
Location: Chennai, India
Daemon App

Hi,

Can some one give me step-by-step reference to write and launch simple (Hello World) kind of Dameon with Launchd?


Thanks
Siva
sivaprakash is offline   0 Reply With Quote
Old Apr 29, 2011, 05:51 AM   #2
KnightWRX
macrumors Pentium
 
KnightWRX's Avatar
 
Join Date: Jan 2009
Location: Quebec, Canada
What language are you targetting for writing your daemon ? Here's a good C reference for the BSD socket API :

http://www.few.vu.nl/~jms/socket-info.html

There's info on there about how to write a server process (daemon) using listen() and accept(). I'd suggest also looking into fork(), as you'll need some kind of parallelism (and multi-process with fork() is easier than pthreads).

Here's the recipe for launchd :

http://homepage.mac.com/kelleherk/ib...930/index.html

Frankly, this all took me about 1 minute to find on Google. Did you even try to search ?
__________________
"What you leave behind is not what is engraved in stone monuments, but what is woven into the lives of others."
-- Pericles
KnightWRX is offline   0 Reply With Quote
Old Apr 29, 2011, 06:39 AM   #3
sivaprakash
Thread Starter
macrumors member
 
Join Date: Mar 2011
Location: Chennai, India
:-) Thanks !!

By the way, I got many articles but they were little high end I just wanted to have something to the ground level so that I can understand well, more over I am just 2 month old Mac Programmer. Sorry about it !!
sivaprakash is offline   0 Reply With Quote
Old May 2, 2011, 02:31 AM   #4
sivaprakash
Thread Starter
macrumors member
 
Join Date: Mar 2011
Location: Chennai, India
Hey

I just want to start a Server program (which is written in Objective-C). To achieve this

- I have to write script (Apple Script or Perl Script) to start the Server Program, where should I put this file?
- Configure plist and put it under /LaunchDaemons folder because it has to work for all users

What I am doing is correct? For some reason it is not starting up?

Thanks
Siva
sivaprakash is offline   0 Reply With Quote
Old May 2, 2011, 03:10 AM   #5
jiminaus
macrumors 65816
 
Join Date: Dec 2010
Location: Sydney
You can put the startup script where ever you like. Or more specifically, it needs to be where ever your launchd .plist file refers to it.

You're putting the .plist in /Library/LaunchDaemons right?

Have you loaded the .plist using launchctl using something like:
Code:
sudo launchctl load -w /Library/LaunchDaemons/com.company.product.plist
Additionally (quoted from the launchctl man page):
Quote:
All system-wide daemons (LaunchDaemons) must be owned by root. Configuration files must not be group- or world-writable.
Here configuration files means launchd .plist files.

Also I don't know if you can execute an apple script or perl script directly from a launchd .plist even with a she-bang line in the script. You might have to directly executed the relevant interpreter and pass the script as an argument to the interpreter. For example, for an AppleScript, you might need to setup the ProgramArguments array like so:

Code:
<key>ProgramArguments</key>
<array>
<string>/usr/bin/osascript</string>
<string>/absolute/path/to/server/script/serverscript</string>
<string>scriptarg1</string>
<string>scriptarg2</string>
<string>etc</string>
</array>

EDIT: On other thing you could do (if you haven't already) is add StandardOutPath and StandardErrorPath keys with string values being absolute paths to files. Then check those files for error messages.

Eg.
Code:
<key>StandardOutPath</key>
<string>/var/tmp/myserver.out</string>
<key>StandardErrorPath</key>
<string>/var/tmp/myserver.err</string>

Last edited by jiminaus; May 2, 2011 at 03:42 AM.
jiminaus is offline   0 Reply With Quote
Old May 2, 2011, 04:46 AM   #6
subsonix
macrumors 68030
 
Join Date: Feb 2008
I think the recommended practice is to run "per user" or "per session" when ever possible, rather than machine wide, simply because you wan't to avoid running as root.
subsonix is offline   0 Reply With Quote
Old May 2, 2011, 05:29 AM   #7
sivaprakash
Thread Starter
macrumors member
 
Join Date: Mar 2011
Location: Chennai, India
Hi


Here is what I did, my perl file saved under /usr/local/siva/test.pl

PHP Code:
$str ="Test Daemon !....";
open FILE">file.txt" or die $!; 
print 
FILE $str
close FILE
and kept my .plist file under "/Library/LaunchDaemons"


Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>local.service.test</string>
    <key>UserName</key>
    <string>root</string>
    <key>ProgramArguments</key>
    <array>
            <string>/usr/local/siva/test.pl</string>
    </array>
</dict>
</plist>
Then I did

$ sudo launchctl load /Library/LaunchDaemons/test.plist

Any stps I am missing ? Do I need to any permissions or something else ? Because in one of the tutorial I read "Remember to make it executable (PERL file); probably best to change the owner/group to root/wheel and set rwxr--r-- permissions." but I dont understand what it is?
sivaprakash is offline   0 Reply With Quote
Old May 2, 2011, 06:05 AM   #8
subsonix
macrumors 68030
 
Join Date: Feb 2008
Quote:
Originally Posted by sivaprakash View Post
Hi


Here is what I did, my perl file saved under /usr/local/siva/test.pl

PHP Code:
$str ="Test Daemon !....";
open FILE">file.txt" or die $!; 
print 
FILE $str
close FILE
and kept my .plist file under "/Library/LaunchDaemons"
You don't need to run this in /Library/LaunchDaemons, so you shouldn't.

From Apple technical note tn2083:

Quote:
If you've decided to implement a background program, you must then determine whether you need an agent or a daemon. The main reason for using a daemon is that you need to share some state between multiple processes in different login sessions. If you don't need this, consider using an agent.
So, put you plist file in ~/Library/LaunchAgent and remove username, root

Can you execute your perl script directly? You need to make it executable with chmod.
subsonix is offline   0 Reply With Quote
Old May 2, 2011, 06:29 AM   #9
jiminaus
macrumors 65816
 
Join Date: Dec 2010
Location: Sydney
While the advice about agents verses daemons is generally good, this is clearly a test setup being done by the OP. If you check his other threads, his ultimate goal server-wise does fit the bill of daemon, it won't work as an agent.

However, the advise of not running as root is valid. You should follow the model of likes of Apache and MySQL. Create a special-purpose, non-root user for the purposes of running your sever. Have all the files owned by this special-purpose user.

In regards to launchd troubles, the files below do work.

/var/tmp/a/test.plist
Code:
$str ="Test Daemon !...."; 
open FILE, ">file.txt" or die $!;  
print FILE $str;  
close FILE;  
exit -1;  # Don't normally do this, see below.
/Library/LaunchDaemons/local.service.test.plist
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>local.service.test</string>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<true/>
	</dict>
	<key>RunAtLoad</key>
	<true/>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/bin/perl</string>
		<string>/var/tmp/a/test.pl</string>
	</array>
	<key>StandardErrorPath</key>
	<string>/var/tmp/a/test.err</string>
	<key>StandardOutPath</key>
	<string>/var/tmp/a/test.out</string>
	<key>WorkingDirectory</key>
	<string>/var/tmp/a</string>
</dict>
</plist>
A word first about the exit -1. The exit -1 in the perl script is only for this test. You would normally not do this. The script launched by launchd is meant to keep running while your server is running. If the script exits, it means the server exited and needs to be relaunched. But this test script exits very quickly. The exit -1 causes an unsuccessful exit, and stops launchd from relaunching the script over and over rapidly.

The primary reason your script failed to run was because you'd coded an on-demand launchd plist file. But you never specified under what conditions the test script should be run, so it never did. You need to include the KeepAlive key like above. This particular KeepAlive setup also implies RunAtLoad, so launchd will immediately run the test script.

Even if you'd got that right, the running of the script would have failed. At no point did you setup perl to run the script. A .pl extension is not enough. You either need a she-bang line at the top of the script, or to explicitly invoke perl like I've done in the .plist file.

Lastly you use a relative path for file.txt in your test script, but what do you expect the working directory to be? You've got to set the in the .plist file.


EDIT: I seems you have very little Unix experience. Writing a server under Mac OS X without Unix server administration experience is going to be bad. I'd suggest you learn how to install, setup and administer a Unix server package such as Apache or MySQL. In doing so you will learn how a Unix server is meant to behave, and give you a model for creating your own server.

Last edited by jiminaus; May 2, 2011 at 06:39 AM.
jiminaus is offline   0 Reply With Quote
Old May 2, 2011, 08:33 AM   #10
sivaprakash
Thread Starter
macrumors member
 
Join Date: Mar 2011
Location: Chennai, India
Hi,

Step 1:-

Here is my PLIST under System/Library/LaunchDaemons/

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>local.service.test</string>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<true/>
	</dict>
	<key>RunAtLoad</key>
	<true/>
	<key>ProgramArguments</key>
	<array>
		<string>/perl</string>
		<string>/users/siva/Test.pl</string>
	</array>
	<key>StandardErrorPath</key>
	<string>/users/siva/test.err</string>
	<key>StandardOutPath</key>
	<string>/users/siva/test.out</string>
	<key>WorkingDirectory</key>
	<string>/users/siva</string>
</dict>
</plist>

Step 2:-

Perl File under Users/Siva/

Code:
$str ="Test Daemon !...."; 
open FILE, ">file.txt" or die $!;  
print FILE $str;  
close FILE;  
exit -1;  # Don't normally do this, see below.
Step 3:-

sudo launchctl load -w /Library/LaunchDaemons/local.service.test.plist

Step 4:-

I ran

10:/ siva$ sudo launchctl list | grep test

and got

- 2 local.service.test

This is exactly I did. But I couldn't see the out put. Can you insert some steps if I have missed or anything like permissions?

Last edited by sivaprakash; May 2, 2011 at 09:08 AM. Reason: Detail steps..
sivaprakash is offline   0 Reply With Quote
Old May 2, 2011, 10:39 AM   #11
chown33
macrumors 603
 
Join Date: Aug 2009
Quote:
Originally Posted by sivaprakash View Post
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>local.service.test</string>
	<key>KeepAlive</key>
	<dict>
		<key>SuccessfulExit</key>
		<true/>
	</dict>
	<key>RunAtLoad</key>
	<true/>
	<key>ProgramArguments</key>
	<array>
		<string>/perl</string>
		<string>/users/siva/Test.pl</string>
	</array>
	<key>StandardErrorPath</key>
	<string>/users/siva/test.err</string>
	<key>StandardOutPath</key>
	<string>/users/siva/test.out</string>
	<key>WorkingDirectory</key>
	<string>/users/siva</string>
</dict>
</plist>
The red-hilited pathname looks wrong to me. It doesn't match jiminous's example, either.

AFAIK, there is no "/perl" executable. There may be a "/usr/bin/perl" executable, as jiminaus showed. Find out using this command in Terminal:
Code:
which perl
Or just follow the given example exactly. Or if you have your own custom-installed version of perl, then use its exact pathname.

And the pathnames "/users/siva" should use the correct case to match the actual directory names. It's a non-issue on a case-insensitive file-system, but you might not always have that. It's better to be exact.
chown33 is offline   0 Reply With Quote
Old May 2, 2011, 05:34 PM   #12
jiminaus
macrumors 65816
 
Join Date: Dec 2010
Location: Sydney
In addition to the possible problem of the path to perl that chown33 pointed out, there's also 2 other potential issues I can see.

The line about your .plist file says /System/Library/LaunchDaemons (a no-no), but you're launchctl comamnd refers to /Library/LaunchDaemons. Make sure you have no versions of your .plist file in /System/Library/LaunchDaemons, and that the latest version is in /Library/LaunchDaemons.

To check the ownership and permissions of the .plist (which is critical), what's the output of this command? (copy and paste the output into code tags, don't paraphrase)
Code:
ls -al /Library/LaunchDaemons/
You need to unload the .plist file, before you reload a newer version.
Code:
sudo launchctl unload -w /Library/LaunchDaemons/local.service.test.plist
I wouldn't expect that to solve your problem, if you have a problem in regards to ownership and permissions, which I suspect you might have.

BTW You probably don't know about the online manual pages. There's a command called man which will display online manual pages. For example, you can read the manual page for launchctl with the command:
Code:
man launchctl
You can get a list of all the launchd .plist keys and their documentation with the command:
Code:
man launchd.plist
You can get the manual page for the man command itself with:
Code:
man man
Lastly the commands for change permissions and ownership are chmod and chown respectively, you might want to read those manual pages.
jiminaus is offline   0 Reply With Quote
Old May 2, 2011, 08:29 PM   #13
subsonix
macrumors 68030
 
Join Date: Feb 2008
Quote:
Originally Posted by jiminaus View Post
While the advice about agents verses daemons is generally good, this is clearly a test setup being done by the OP. If you check his other threads, his ultimate goal server-wise does fit the bill of daemon, it won't work as an agent.
How about creating a simple launchd job first? Get Lingon from the App store read this: http://www.macworld.com/article/4870...eekfactor.html

The guy is asking for a "Hello world" example.

Quote:
Originally Posted by jiminaus View Post
Create a special-purpose, non-root user for the purposes of running your sever. Have all the files owned by this special-purpose user.
Which means it can be run in a "per user" context, which is what I suggested.
There is an interesting talk about launchd by Dave Zarzycki from Apple who wrote launchd at Google tech talk: http://www.youtube.com/watch?v=mLwn_TbBntI
subsonix is offline   0 Reply With Quote
Old May 2, 2011, 09:11 PM   #14
jiminaus
macrumors 65816
 
Join Date: Dec 2010
Location: Sydney
Quote:
Originally Posted by subsonix View Post
How about creating a simple launchd job first? Get Lingon from the App store read this: http://www.macworld.com/article/4870...eekfactor.html

The guy is asking for a "Hello world" example.
Fair enough. But a daemon and an agent are setup the same way, just in different directories.

Quote:
Which means it can be run in a "per user" context, which is what I suggested.
There is an interesting talk about launchd by Dave Zarzycki from Apple who wrote launchd at Google tech talk: http://www.youtube.com/watch?v=mLwn_TbBntI
Except an agent is only started with a user is logged in, if I'm not mistaken. The scheduled tasks part of the OP's server plans won't run if a user is not logged in.
jiminaus is offline   0 Reply With Quote
Old May 2, 2011, 09:53 PM   #15
subsonix
macrumors 68030
 
Join Date: Feb 2008
Quote:
Originally Posted by jiminaus View Post
Except an agent is only started with a user is logged in, if I'm not mistaken. The scheduled tasks part of the OP's server plans won't run if a user is not logged in.
That is the difference between "per session" and "per user" context, "per session" is placed in: ~/Library/LaunchAgents

"per user" in: /Library/LaunchAgents, it will last over login and logout.
subsonix is offline   0 Reply With Quote
Old May 2, 2011, 10:17 PM   #16
jiminaus
macrumors 65816
 
Join Date: Dec 2010
Location: Sydney
Quote:
Originally Posted by subsonix View Post
That is the difference between "per session" and "per user" context, "per session" is placed in: ~/Library/LaunchAgents

"per user" in: /Library/LaunchAgents, it will last over login and logout.
Are you able to test this to be the case? I'm in foreign PC territory right now (I'm at work). My understanding is that a session doesn't start until a user login in. In the context of fast user switching, there can be multiple sessions. Am I wrong?

Also I was thinking the server would need to run as the server user regardless of who is actually logged into the Mac. For that the OP needs to set the UserName and GroupName keys in the .plist file, and they only work when launchd is run as root. My understanding (again I can't test this right now) is that agents are run by the 2nd launchd instance that running as the logged in user, only daemons are run by the instance running as root.
jiminaus is offline   0 Reply With Quote
Old May 2, 2011, 10:28 PM   #17
subsonix
macrumors 68030
 
Join Date: Feb 2008
Quote:
Originally Posted by jiminaus View Post
Are you able to test this to be the case? I'm in foreign PC territory right now (I'm at work). My understanding is that a session doesn't start until a user login in. In the context of fast user switching, there can be multiple sessions. Am I wrong?
I'm not saying it should be run in a "per session" context but "per user". If you look at the presentation of launchd in the link this is what is being explained. In a "per session" layer the launch agents come and go with login sessions, in the "per user" layer it stays, which is appropriate if you for example want to run a web server. System-wide is only necessary if you must create a service that needs to operate across multiple accounts on the same computer, it's a "per machine" context.
subsonix is offline   0 Reply With Quote
Old May 2, 2011, 10:36 PM   #18
jiminaus
macrumors 65816
 
Join Date: Dec 2010
Location: Sydney
Can't get away with watching youtube at work. I'll watch it after. I think I need because what you're saying in conflicting with my understanding.
jiminaus is offline   0 Reply With Quote
Old May 2, 2011, 10:50 PM   #19
subsonix
macrumors 68030
 
Join Date: Feb 2008
Quote:
Originally Posted by jiminaus View Post
Can't get away with watching youtube at work. I'll watch it after. I think I need because what you're saying in conflicting with my understanding.
Actually the context seems to be set by the: LimitLoadToSessionType key to for example: Background, Aqua, LoginWindow. But the layer which transcends login sessions was added in Leopard apparently. So the difference between ~/ and / for LaunchAgents is only the access, administrator or user.
subsonix is offline   0 Reply With Quote
Old May 3, 2011, 12:56 AM   #20
sivaprakash
Thread Starter
macrumors member
 
Join Date: Mar 2011
Location: Chennai, India
Wow !! It works for me.

Many Thanks to every one !!

Mistakes I did:-

- I did realized that there is a folder called Var and Library at the root level since it is not there in my explorer

Like jiminaus pointed out minimum (I would say NIL) knowledge in UNIX environment caused all the issues.

Thanks
Siva
sivaprakash is offline   0 Reply With Quote
Old May 3, 2011, 03:06 AM   #21
jiminaus
macrumors 65816
 
Join Date: Dec 2010
Location: Sydney
Quote:
Originally Posted by sivaprakash View Post
Wow !! It works for me.

Many Thanks to every one !!

Mistakes I did:-

- I did realized that there is a folder called Var and Library at the root level since it is not there in my explorer

Like jiminaus pointed out minimum (I would say NIL) knowledge in UNIX environment caused all the issues.

Thanks
Siva
Glad you got've this working so far.

There's lot of "under the hood" stuff that you won't see in the GUI. This is because the vastly greater majority of Mac users both don't want to and shouldn't see it.

While I think you're best off using the Terminal to access these parts, you can get the Finder to show these hidden folders. In the terminal, enter this command.
Code:
defaults write com.apple.finder AppleShowAllFiles TRUE && killall Finder
Now if you into your Macintosh HD you'll see all the hidden files and folders as ghost icons.
jiminaus is offline   0 Reply With Quote
Old May 4, 2011, 07:46 PM   #22
Mr.Texor
macrumors regular
 
Join Date: Apr 2007
ok this is only a joke.. but after reading this thread, all I could think was this.


(again, it's only a joke)
Attached Images
 
Mr.Texor is offline   0 Reply With Quote
Old May 9, 2011, 04:58 AM   #23
sivaprakash
Thread Starter
macrumors member
 
Join Date: Mar 2011
Location: Chennai, India
@ Texor - What are you trying to convey ?
sivaprakash is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Resolved: VirtualBox Headless won't run as a daemon TheAnvil OS X Mavericks (10.9) 0 Apr 11, 2014 10:22 AM
chown33 - launchagent-daemon help if you could assist NixxereBB Mac Programming 3 Jun 11, 2013 09:26 PM
MPD (music player daemon) hp. Digital Audio 0 May 2, 2013 06:36 PM
com.onlinebackup.daemon.plist conflict with Aperture 3 digitalnomad Mac Applications and Mac App Store 0 Aug 23, 2012 03:10 AM
Absinthed daemon renamart iOS 5 and earlier 3 Aug 20, 2012 04:43 PM

Forum Jump

All times are GMT -5. The time now is 03:19 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC