Link to home
Start Free TrialLog in
Avatar of osxman
osxman

asked on

Copy files on remote iMac

I  need to copy the local 'user' directory into another local directory ( user back-up) on the same machine. I have an ARD task server and admin machine. Is it possible to do this with ARD? I would also want to  propagate "loca admin"  read write permissions on the user back-up folder. I need to do this on 30 machines, which is why I looking to do this as a task.

TIA
Avatar of Bryan_Vines
Bryan_Vines
Flag of United States of America image

I don't think ARD can do this natively, but we can help ARD a little bit with an AppleScript applet.

Paste the attached script into AppleScript Editor, then make any necessary edits to the Administrator name, whether you want the Admin's home backed up, etc. Save it as an Application, and (because it needs the Admin password embedded in it), make sure you check the Run only box. This should keep your end-users from getting that password.

Deploy the resulting application with ARD, and then use ARD's "run application" feature to run the backup whenever you want.

--
Bryan Vines

 
(* BACK UP LOCAL USERS *)
-- ©2011 Bryan Vines

-- PURPOSE:
-- This script will back up the specified subfolders of all local users; the backups are stored in /Users/Shared. Save this script as an application, and save it as "Run only." Deploy it via ARD, then you can use ARD's "run application" feature to run it whenever you like.

(* THE SCRIPT *)
-- The login credentials of the administrator on the computer.
-- Generally speaking, this is a bad idea, but if you save this script as an application and deny editing, it should be reasonably safe from most users' prying eyes.
set the adminUserName to "sysadmin"
set the adminPassword to "admin123"

-- If you want to exclude your admin user from the user list, set its short name here.
-- Leave blank to return all local users.
set administratorShortNameToOmit to ""

-- Set the full path to your backup destination here. Make sure to include a trailing slash.
set the backupDestination to "/Users/Shared/"

-- Get the user list.
set the localUserList to getLocalUserList(administratorShortNameToOmit)

-- Back up these users to the backup destination folder.
repeat with currentUser in the localUserList
	-- As an example, we will only back up the Desktop folder.
	-- You can duplicate the line below for each folder you want to back up.
	-- In my work environment I would typically only back up Desktop and Documents.
	
	backupUserData(currentUser, "Desktop", backupDestination, adminUserName, adminPassword)
	--backupUserData(currentUser, "Documents", backupDestination, adminUserName, adminPassword)
	--backupUserData(currentUser, "Library", backupDestination, adminUserName, adminPassword)
	--backupUserData(currentUser, "Movies", backupDestination, adminUserName, adminPassword)
	--backupUserData(currentUser, "Music", backupDestination, adminUserName, adminPassword)
	--backupUserData(currentUser, "Pictures", backupDestination, adminUserName, adminPassword)
	--backupUserData(currentUser, "Public", backupDestination, adminUserName, adminPassword)
	--backupUserData(currentUser, "Sites", backupDestination, adminUserName, adminPassword)
end repeat

(* SUBROUTINES *)
on backupUserData(theUsertoBackUp, theSubfolderToBackUp, theBackupDestination, theAdminUser, theAdminPass)
	set the homeFolderToBackUp to getHomePath(theUsertoBackUp)
	
	-- Use ditto to copy the specified folder to our backup destination.
	do shell script "ditto " & the homeFolderToBackUp & "/" & theSubfolderToBackUp & " " & theBackupDestination & theUsertoBackUp & "/" & theSubfolderToBackUp user name theAdminUser password theAdminPass with administrator privileges
	
	-- Set ownership to the admin user.
	do shell script "chown -R " & theAdminUser & " " & theBackupDestination & theUsertoBackUp user name theAdminUser password theAdminPass with administrator privileges
end backupUserData

on getHomePath(userShortName)
	-- This subroutine returns the home directory path for the specified user.
	
	-- Get path to home folder for this user.
	set the homeDirectory to text 19 thru end of (do shell script "dscl . -read /Users/" & userShortName & "|grep NFSHomeDirectory")
	
	-- Return the home directory path.
	return the homeDirectory
end getHomePath

on getLocalUserList(userNameToIgnore)
	-- Get a list of the short names of local user accounts.
	
	--Create an empty list to hold the user names which are discovered.
	set the listOfUserNames to {}
	
	-- Get a list of UniqueIDs of local users on this computer.
	set the listOfUniqueIDs to getUserAccountUniqueIDs()
	
	-- Look at each user record.
	repeat with currentUniqueID in the listOfUniqueIDs
		
		-- Get the short name of the user associated with this UniqueID.
		set the currentUserName to the first word of (do shell script "dscl . -list /Users UniqueID|grep " & the currentUniqueID)
		
		-- If the short name of this user is a user we don't want to list, ignore it.
		if the currentUserName is not the userNameToIgnore then
			-- Add this short name to the list of local user names.
			set the listOfUserNames to the listOfUserNames & the currentUserName
		end if
	end repeat
	
	--Return with the list of local user names.
	return listOfUserNames
end getLocalUserList


on getUserAccountUniqueIDs()
	-- Local user account UniqueIDs begin at 500.
	-- This routine returns a list of local user account UniqueIDs.
	
	-- Create an empty list to hold the UniqueIDs which are discovered.
	set the listOfUniqueIDsGreaterThan500 to {}
	
	-- Get a list of all user records on the computer. This includes system daemons.
	set the listOfUserRecords to paragraphs of (do shell script "dscl . -list /Users UniqueID")
	
	-- Look at each user record.
	repeat with currentUserRecord in listOfUserRecords
		
		-- Get the UniqueID for the record.
		set the currentUserID to the (last word of the currentUserRecord as integer)
		
		-- If the Unique ID > 500, add it to the list we created earlier.
		if the currentUserID is greater than 500 then set the listOfUniqueIDsGreaterThan500 to listOfUniqueIDsGreaterThan500 & the currentUserID
	end repeat
	
	-- Return with the list we discovered.
	return listOfUniqueIDsGreaterThan500
end getUserAccountUniqueIDs

Open in new window

Avatar of osxman
osxman

ASKER

Bryan,

Thanks for the script. I have got it almost working on my local mac for now. It copys the content of my user directory omitting the admin into my backup folder. But then I get the following error:

error ditto can't get real path for source number 1

Also, what does the code after "end backupUserData" do? do I need it?
 User generated image
ASKER CERTIFIED SOLUTION
Avatar of Bryan_Vines
Bryan_Vines
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of osxman

ASKER

Sorry but I get the same error?
Try this:

Comment out the do shell script "ditto" line by putting two dashes in front of it, then add this line immediately below:

display dialog "ditto " & quoted form of (the homeFolderToBackUp & "/" & theSubfolderToBackUp) & " " & quoted form of (theBackupDestination & theUsertoBackUp & "/" & theSubfolderToBackUp)
This will display a dialog box showing what the ditto command is trying to do. Screenshot that dialog box and then click its Cancel button. Post the screenshot here so I can see what it's trying to do.

Also, I'm running this on Snow Leopard, but it should work the same on Leopard.

--
Bryan Vines
Avatar of osxman

ASKER

User generated image
Avatar of osxman

ASKER

ah! just saw an error pop up saying cannot locate student folder! I looked in accounts and there was a student account, but no folder in users. deleted the student account and now it works.

Thanks for your expert help. The display function is very useful for trouble-shooting!

:O)
Avatar of osxman

ASKER

One more thing. I have opened up ARD and can see the destination computer. What function should i use to run the script? I can see Copy, Install, Unix, Spotlight?

I have only ever used ARD for remote control so this is new and exciting stuff!

Cheers
Save the script as a run-only application, and copy it to the remote computer. Then, you should be able to tell ARD to run an application on the remote computer. I don't remember which menu it's on, and I don't have ARD handy on the computer I'm using right this moment, so you might want to check its Help system.

I can later, but it'll be several hours before I can get to a computer with ARD on it. :)

--
Bryan Vines
Avatar of osxman

ASKER

Bryan,

You are a star! I am so excited about what you have shown me. I got it working with ARD. I have just performed a task on 30 iMacs that would have taken me so much time, manually going around each one.

Now, I can't wait to learn more about apple scripting.

So chuffed! LOL

Thanks again!
Avatar of osxman

ASKER

What a true Expert. Patience and quick help!
Remember, the script as I posted it is only getting the Desktop folder for the users. Make sure to uncomment the other lines in the main body of the script to pick up the other folders as well, if you require them.

Thanks for the compliment!

--
Bryan Vines
Avatar of osxman

ASKER

Ah, forget about that!

Also I just realised a mistake. I also need a user called Staff to be able to read/write access to the back up folder. Is it easy to add?

:O)
Avatar of osxman

ASKER

I meant to say a mistake I made in not asking in the original post :O)
If the user named Staff has a group in common with the Admin user, you can add some additional permissions in the backupUserData subroutine. In this example, I will assume you have a group named "backups".

Immediately below this code:

	-- Set ownership to the admin user.
	do shell script "chown -R " & theAdminUser & " " & quoted form of (theBackupDestination & theUsertoBackUp) user name theAdminUser password theAdminPass with administrator privileges

Open in new window


Add the following:

	-- Set group membership to the backups group.
	do shell script "chgrp -R backups " & quoted form of (theBackupDestination & theUsertoBackUp) user name theAdminUser password theAdminPass with administrator privileges

	-- Set owner and group permissions to read & write; set others to no access.
	do shell script "chmod -R 770 " & quoted form of (theBackupDestination & theUsertoBackUp) user name theAdminUser password theAdminPass with administrator privileges

Open in new window

I hope that helps!

There's also a way to do this via ACLs -- Access Control Lists -- but I'm not yet well-versed in using them.

--
Bryan Vines
Avatar of osxman

ASKER

Thanks for the reply Bryan,

"the user named Staff has a group in common with the Admin user" - no, the staff user is just a standard local user. The problem I ahve inherited is that network users (AD) despite having a network folder in the dock keep saving work to their local account on multiple macs around the school ("force local home on startup disk" setting is used when binding to AD) - apparently this was set to resolve problems with applications, etc

Coursework is due and I have got teachers constantly requesting for me to search for files, etc on quite a few macs spread around the school as the student cant find their work. Anyway, my plan was to create a back-up of all user's desktop and documents accept admin from the user folder to a folder called back-up on the same drive, on each mac. Give this newly created folder read\write access for staff recursively so the teacher can log on as "staff" and browse through it and copy any lost work on to a USB pen or to the 'shared area sharepoint' - they are happy to do this as I am too busy elsewhere and they don't have to wait for me.

I have done this manually on about 5 macs and it works fine, just laborious, which is why I want to use ARD.

Meanwhile I am trying to work out how to put a link to their AD network share in the "places" sidebar to resolve this problem once and for all. Easier said then done! still can't figure it out.
 
I hope this makes sense, and thanks for getting back to me.

OK, I've revised the script to add Access Control Entries to the backup files, which will allow your "designated reviewer" -- the Staff account -- to read the backup files.

In Mac OS X, there's already a group named staff, so I don't know if also having a user named staff is a good idea, but nevertheless this script tries to set the Access Control Entry to apply to a user, not a group.

Note also that I changed this script to back up only the Sites folder -- it made for a shorter test cycle. Comment or uncomment the appropriate lines in the script to back up the folders you're interested in.

Hopefully this will work for you.

--
Bryan Vines

 
(* BACK UP LOCAL USERS *)
-- ©2011 Bryan Vines

-- PURPOSE:
-- This script will back up the specified subfolders of all local users; the backups are stored in /Users/Shared. Save this script as an application, and save it as "Run only." Deploy it via ARD, then you can use ARD's "run application" feature to run it whenever you like.

(* THE SCRIPT *)
-- SETUP: 
--Define the login credentials of the administrator on the computer. Generally speaking, this is a bad idea, but if you save this script as an application and deny editing, it should be reasonably safe from most users' prying eyes.
-- Define a designated reviewer. This is the user responsible for examining the backups to find files.

set the adminUserName to "sysadmin"
set the adminPassword to "admin123"
set the designatedReviewer to "sysadmin"

-- If you want to exclude your admin user from the user list, set its short name here.
-- Leave blank to return all local users.
set administratorShortNameToOmit to ""

-- Set the full path to your backup destination here. Make sure to include a trailing slash.
set the backupDestination to "/Users/Shared/Back Up/"

-- Get the user list.
set the localUserList to getLocalUserList(administratorShortNameToOmit)

-- Back up these users to the backup destination folder.
repeat with currentUser in the localUserList
	-- As an example, we will only back up the Sites folder -- It has few files, but enough to prove the concept.
	-- Uncomment each line below to back up the folder it refers to; comment lines to omit folders.
	-- In my work environment I would typically only back up Desktop and Documents.
	
	--backupUserData(currentUser, "Desktop", backupDestination, adminUserName, adminPassword, designatedReviewer)
	--backupUserData(currentUser, "Documents", backupDestination, adminUserName, adminPassword, designatedReviewer)
	--backupUserData(currentUser, "Library", backupDestination, adminUserName, adminPassword, designatedReviewer)
	--backupUserData(currentUser, "Movies", backupDestination, adminUserName, adminPassword, designatedReviewer)
	--backupUserData(currentUser, "Music", backupDestination, adminUserName, adminPassword, designatedReviewer)
	--backupUserData(currentUser, "Pictures", backupDestination, adminUserName, adminPassword, designatedReviewer)
	--backupUserData(currentUser, "Public", backupDestination, adminUserName, adminPassword, designatedReviewer)
	backupUserData(currentUser, "Sites", backupDestination, adminUserName, adminPassword, designatedReviewer)
end repeat

(* SUBROUTINES *)
on backupUserData(theUsertoBackUp, theSubfolderToBackUp, theBackupDestination, theAdminUser, theAdminPass, theDesignatedUser)
	set the homeFolderToBackUp to getHomePath(theUsertoBackUp)
	
	-- Use ditto to copy the specified folder to our backup destination.
	do shell script "ditto " & quoted form of (the homeFolderToBackUp & "/" & theSubfolderToBackUp) & " " & quoted form of (theBackupDestination & theUsertoBackUp & "/" & theSubfolderToBackUp) user name theAdminUser password theAdminPass with administrator privileges
	
	-- Set ownership to the admin user.
	do shell script "chown -R " & theAdminUser & " " & quoted form of (theBackupDestination & theUsertoBackUp) user name theAdminUser password theAdminPass with administrator privileges
	
	-- Set the POSIX permissions to allow access only by the owner.
	do shell script "chmod -R 700 " & quoted form of (theBackupDestination & theUsertoBackUp) user name theAdminUser password theAdminPass with administrator privileges
	
	-- Remove any existing Access Control Entries on the backed up data.
	do shell script "chmod -RN " & quoted form of (theBackupDestination & theUsertoBackUp) user name theAdminUser password theAdminPass with administrator privileges
	
	-- Add an Access Control Entry to every backed up item, allowing read access by another designated user.
	do shell script "chmod -R +a# 0 " & quoted form of ("user:" & theDesignatedUser & " allow list,search,read") & " " & quoted form of (theBackupDestination & theUsertoBackUp) user name theAdminUser password theAdminPass with administrator privileges
end backupUserData

on getHomePath(userShortName)
	-- This subroutine returns the home directory path for the specified user.
	
	-- Get path to home folder for this user.
	set the homeDirectory to text 19 thru end of (do shell script "dscl . -read /Users/" & userShortName & "|grep NFSHomeDirectory")
	
	-- Return the home directory path.
	return the homeDirectory
end getHomePath

on getLocalUserList(userNameToIgnore)
	-- Get a list of the short names of local user accounts.
	
	--Create an empty list to hold the user names which are discovered.
	set the listOfUserNames to {}
	
	-- Get a list of UniqueIDs of local users on this computer.
	set the listOfUniqueIDs to getUserAccountUniqueIDs()
	
	-- Look at each user record.
	repeat with currentUniqueID in the listOfUniqueIDs
		
		-- Get the short name of the user associated with this UniqueID.
		set the currentUserName to the first word of (do shell script "dscl . -list /Users UniqueID|grep " & the currentUniqueID)
		
		-- If the short name of this user is a user we don't want to list, ignore it.
		if the currentUserName is not the userNameToIgnore then
			-- Add this short name to the list of local user names.
			set the listOfUserNames to the listOfUserNames & the currentUserName
		end if
	end repeat
	
	--Return with the list of local user names.
	return listOfUserNames
end getLocalUserList


on getUserAccountUniqueIDs()
	-- Local user account UniqueIDs begin at 500.
	-- This routine returns a list of local user account UniqueIDs.
	
	-- Create an empty list to hold the UniqueIDs which are discovered.
	set the listOfUniqueIDsGreaterThan500 to {}
	
	-- Get a list of all user records on the computer. This includes system daemons.
	set the listOfUserRecords to paragraphs of (do shell script "dscl . -list /Users UniqueID")
	
	-- Look at each user record.
	repeat with currentUserRecord in listOfUserRecords
		
		-- Get the UniqueID for the record.
		set the currentUserID to the (last word of the currentUserRecord as integer)
		
		-- If the Unique ID > 500, add it to the list we created earlier.
		if the currentUserID is greater than 500 then set the listOfUniqueIDsGreaterThan500 to listOfUniqueIDsGreaterThan500 & the currentUserID
	end repeat
	
	-- Return with the list we discovered.
	return listOfUniqueIDsGreaterThan500
end getUserAccountUniqueIDs

Open in new window

Avatar of osxman

ASKER

Bryan,

Worked beautifully when trying on my local mac. Changed staff account to teacher.

One problem.

on  remote mac nobody is logged in.
 I copy your script via ARD as a 'copy only task' and this succeeds.
 If I copy your script as copy with "after copying, open items" tick it fails
 if I log into remote mac and perform the latter it succeeds. Is this how it should be?

I have found that once your script has been copied to the remote computer, I can send a unix command "using root user"  to open the copied script and this works, regardless of whether the remote mac has a user logged in or out.

So I am right to think you cannot "open items" you have copied on remote mac when nobody is logged in?

Thanks again for your after sales support - as it where :O)