I want to write a small app that can start off up to 3 instances of rsync. How do I initiate 3 threads of this command? I can only seem to do one command line at a time right now (skill level!) using the ‘do shell script’ command. Can someone point me in the right direction?
You might be able to use NSTask to run multiple commands concurrently.
Example:
on caffeinateSystem_(sender)
-- SET UP THE NSTASK
set pmsetTask to current application's NSTask's alloc()'s init()
pmsetTask's setLaunchPath_("/usr/bin/pmset")
pmsetTask's setArguments_({"noidle"})
-- LAUNCH THE NSTASK
pmsetTask's |launch|()
end caffeinateSystem_
If you need to get the output of the task, you can set up NSPipe like this:
property pingTask : missing value
on runPingTest_(sender)
set pingTask to current application's NSTask's alloc()'s init()
set outputPipe to current application's NSPipe's pipe()
pingTask's setStandardOutput_(outputPipe)
pingTask's setStandardError_(outputPipe)
pingTask's setLaunchPath_("/sbin/ping")
pingTask's setArguments_({"-c", "25", "google.com"})
current application's NSNotificationCenter's defaultCenter()'s addObserver_selector_name_object_(me, "pingReadPipe:", "NSFileHandleReadCompletionNotification", pingTask's standardOutput()'s fileHandleForReading())
current application's NSNotificationCenter's defaultCenter()'s addObserver_selector_name_object_(me, "pingEndPipe:", "NSTaskDidTerminateNotification", pingTask)
pingTask's standardOutput()'s fileHandleForReading()'s readInBackgroundAndNotify()
pingTask's |launch|()
end runPingTest_
on pingReadPipe_(aNotification)
set dataString to aNotification's userInfo's objectForKey_("NSFileHandleNotificationDataItem")
set newString to ((current application's NSString's alloc()'s initWithData_encoding_(dataString, current application's NSUTF8StringEncoding)))
-- do other stuff
end pingReadPipe_
on pingEndPipe_(aNotification)
current application's NSNotificationCenter's defaultCenter()'s removeObserver_name_object_(me, "NSTaskDidTerminateNotification", pingTask)
current application's NSNotificationCenter's defaultCenter()'s removeObserver_name_object_(me, "NSFileHandleReadCompletionNotification", pingTask's standardOutput()'s fileHandleForReading())
end pingEndPipe_
I must have a thick skull as I can’t seem to correctly apply your sample code to ‘rsync’.
My goal is to have to app ask the user up front for a source, and up to 3 destinations. Then, the app will note how many destinations were specified and start up to 3 instances of rsync using the same source.
I can’t get the code correct for one source, one destination. This is an exercise for me since I know how to simply do this in Terminal. I’d like to challenge myself with a GUI app. Do you happen to have a moment to customize the code above for the rsync binary?
I haven’t ever really used rsync for anything, but this worked for me:
set aSource to posix path of (choose folder with prompt "Choose a source:")
set aDestination to posix path of (choose folder with prompt "Choose a destination:")
set rsyncTask to current application's NSTask's alloc()'s init()
rsyncTask's setLaunchPath_("/usr/bin/rsync")
rsyncTask's setArguments_({"-r", aSource, aDestination})
rsyncTask's |launch|()
What specifically is not working for you? Are you receiving any errors or warnings?
Update:
Here’s a slightly more complicated version:
property rsyncTask : missing value
-- Application launches, runs task handler
on applicationWillFinishLaunching_(aNotification)
my runTask_(me)
end applicationWillFinishLaunching_
on runTask_(sender)
-- ask user to define source and destination
set aSource to posix path of (choose folder with prompt "Choose a source:")
set aDestination to posix path of (choose folder with prompt "Choose a destination:")
-- set up nstask/rsync
set rsyncTask to current application's NSTask's alloc()'s init()
set outputPipe to current application's NSPipe's pipe()
rsyncTask's setStandardOutput_(outputPipe)
rsyncTask's setStandardError_(outputPipe)
rsyncTask's setLaunchPath_("/usr/bin/rsync")
rsyncTask's setArguments_({"-rv", aSource, aDestination})
-- set up notification center observers
current application's NSNotificationCenter's defaultCenter()'s addObserver_selector_name_object_(me, "rsyncTaskReadPipe:", "NSFileHandleReadCompletionNotification", (rsyncTask's standardOutput()'s fileHandleForReading()))
current application's NSNotificationCenter's defaultCenter()'s addObserver_selector_name_object_(me, "rsyncEndPipe:", "NSTaskDidTerminateNotification", rsyncTask)
rsyncTask's standardOutput()'s fileHandleForReading()'s readInBackgroundAndNotify()
rsyncTask's |launch|()
end runTask
-- reading task output
on rsyncTaskReadPipe_(aNotification)
set dataString to aNotification's userInfo's objectForKey_("NSFileHandleNotificationDataItem")
set newString to ((current application's NSString's alloc()'s initWithData_encoding_(dataString, current application's NSUTF8StringEncoding)))
log newString
aNotification's object()'s readInBackgroundAndNotify()
end rsyncTaskReadPipe_
-- removing observer when task completes
on rsyncEndPipe_(aNotification)
current application's NSNotificationCenter's defaultCenter()'s removeObserver_name_object_(me, "NSTaskDidTerminateNotification", rsyncTask)
current application's NSNotificationCenter's defaultCenter()'s removeObserver_name_object_(me, "NSFileHandleReadCompletionNotification", rsyncTask's standardOutput()'s fileHandleForReading())
log "complete"
end rsyncEndPipe_