Script to use in policy that copies file from remote share to client

jevans76
New Contributor

Hi,

I'm quite new to Casper and administering Macs in general.

I'm looking for a way to script copying a file from the JSS/Scripts directory on my distribution point to the local client

I've done some research and found "scp" but I can't seem to get the syntax right?

scp admin@192.168.101.75:/JSS/Scripts/test.txt .

I get prompted for the password, but then I get the following error:

scp: /JSS/Scripts/test.txt: No such file or directory

Could someone point me in the right direction? Is this even the solution I should be using, or is there an easier way with Casper to copy a file from a remote server share to a local client?

Thanks

1 ACCEPTED SOLUTION

davidacland
Honored Contributor II

Hi @jevans76,

scp would certainly be one way to do it. The syntax described by steve is correct, its basically:

scp source destination

As the source (or target) file is on a remote computer the syntax is:

scp user@host:/path/to/file /path/to/destination/folder/

In your example it looks like you are trying to copy the file "/JSS/Scripts/test.txt" from the host "192.168.101.75" to the current location on the computer the script is running on. The error is saying that "/JSS/Scripts/test.txt" doesn't exist on the source computer "192.168.101.75", or if the authentication is being rejected, its not getting far enough to see the file.

For this to be unattended, you will need to create a key pair. We've documented the steps here:

http://www.amsys.co.uk/2012/blog/securely-transfer-encrypted-info-with-password-less-rsync-over-ssh/...

It refers to Rsync but the main bit you will need is the key pair part.

It would be great if the JSS had the ability to do simple file copies (a bit like ARD) to target location without needing to create packages. For now, if you do want a simpler (although slightly convoluted) way to get a file sent out, you could just create a package for it in Composer and push it out that way.

Hope this helps.

View solution in original post

13 REPLIES 13

stevevalle
Contributor III

Try something like this:

scp admin@192.168.101.75:/Volumes/JSS/Scripts/test.txt /Users/steve/Desktop

/Volumes/JSS (if the name of the HD is JSS) then the path to where to save the file (in the above code, the desktop)

Hop that helps

Steve

calum_oac
New Contributor

There is probably a much better way than using scp to do what your after

Questions:
What are you actually trying to accomplish? ie. For what purpose are you trying to copy a file to a client?
What is the remote file server? Is it one server? is your JSS? Distribution point? What kind of services are running on that server? http? smb? afp?
What is the file your trying to copy? Is it a file? directory? script? package? application?

davidacland
Honored Contributor II

Hi @jevans76,

scp would certainly be one way to do it. The syntax described by steve is correct, its basically:

scp source destination

As the source (or target) file is on a remote computer the syntax is:

scp user@host:/path/to/file /path/to/destination/folder/

In your example it looks like you are trying to copy the file "/JSS/Scripts/test.txt" from the host "192.168.101.75" to the current location on the computer the script is running on. The error is saying that "/JSS/Scripts/test.txt" doesn't exist on the source computer "192.168.101.75", or if the authentication is being rejected, its not getting far enough to see the file.

For this to be unattended, you will need to create a key pair. We've documented the steps here:

http://www.amsys.co.uk/2012/blog/securely-transfer-encrypted-info-with-password-less-rsync-over-ssh/...

It refers to Rsync but the main bit you will need is the key pair part.

It would be great if the JSS had the ability to do simple file copies (a bit like ARD) to target location without needing to create packages. For now, if you do want a simpler (although slightly convoluted) way to get a file sent out, you could just create a package for it in Composer and push it out that way.

Hope this helps.

jevans76
New Contributor

Thanks everyone,

What I'm trying to achieve is copying a licensing file from my afp: JSS repo to client machines that have a particular app installed on them.

For some reason, despite packaging the app in question (Sibelius) using Composer, and including the licensing server information, this particular app has known issues with Yosemite, and the license file doesn't get written to the required location on the client, despite it being included in the Composer package.

I was hoping that I could just upload the licensing file to the JSS repository, and have it copied across to clients by capturing clients with Sibelius installed using a Smart Computer Group, i.e. "application title IS "Sibelius.app", then copying the licensing file to them using a policy.

I found that I can check for the presence of files and even delete them if present, but not copy them them to the client if they aren't.

I find it quite frustrating that Casper purports to be an all in one solution, but I'm still having to resort to ARD, etc to perform simple file copies unless I want to create a package. Of course ARD doesn't have the smarts behind it to automate checking for certain conditions to exist prior to copying out the file copy.

stevevalle
Contributor III

@jevans76

You can create a policy that searches for specific files & delete if found. Have a look at the Files and Processes section when creating a new policy.

You can also run a script in the same policy to copy from your network volume to a specific location.

I haven't tried it but it might help.

Steve

bentoms
Release Candidate Programs Tester

@jevans76, another option would be creating a DMG of the file in composer & deploy the file via a policy.

If you index the DMG, it can then be uninstalled via a policy or remote.

If you create the DMG in, say, /Users/bob/Desktop/ it will lay down that structure, so if Bob has an account on a Mac you've targeted.. It will appear on the desktop.

You can also tick FEU: to fill existing user accounts, which will add the file in the DMG in the location to all accounts (so not just bob.. But any accounts).

And/or you can tick FUT's.. Which adds the item(s) from the DMG to the user template.. So when a new user logs in.. They have the file there.

bentoms
Release Candidate Programs Tester

@jevans76, taking your latter example. It should be easy as creating a Smart Group that is based on Sibelius being installed.

Then create the DMG of the license file, tick FEU & FUT. Upload to Casper Admin & index.

Then create a policy that is scoped to the smart group "Has Sibelius.app" & the policy would then install the DMG.

bsuggett
Contributor II

Dear All,

We have to do this type of thing all the time....

Depending on the software vendors licensing model, "NODE" locked licensing refers to a product activated for a single machine. A file either gets updated for created containing the activation unique to that machines GUID or Mac address. This file is then unique to only that machine.

We classify these applications as TIER5 which require human intervention to activate/ license the software product.

Applications requiring no product activation are classify TIER2 in our environment.

To make future rebuilds manageable, we collect the activated files for each machine. Rename them to the source machines serial number upon collection. Store these up on the DP ready for redeployment upon a re-image/rebuild. Redeploy each file via a script we've made in the deployment policy.

Whilst the initial deployment is TIER5 requiring human interaction. The subsequent re-deployments of the applications and each machines unique activated file is automatic. Making it there after TIER2. Thus no reactivation is required.

Our script is below...

Please note the parameter fields. We've named them accordingly

Parameter 4 = DP String 2 Search 4
Parameter 5 = Source Path excl /Volumes/Mount
Parameter 6 = Source File
Parameter 7 = Destination Path
Parameter 8 = Destination File
Parameter 9 = Destination File Permission eg 755

Parameter 4 = DP String 2 Search 4. This searches the volumes directory for your string. This is unique to our environment because we don't name our fileshares the same. ie Caspershare. We name them referencing the DP it is. ie JSS-DP-PRO-1-Share, JSS-DP-PRO-2-Share, JSS-DP-PRO-3-Share. As this fixes issues talked about here https://jamfnation.jamfsoftware.com/discussion.html?id=10178

Parameter 6 = Source File. Isn't mandatory and if left blank the script uses the machines serial number as a reference source file.

Parameter 9 = Destination File Permission eg 755. Isn't mandatory and if left blank the script leaves the permission on the destination file as ROOT.

The next post will have the script syntax which you can copy out as I don't know how to attach a file....

bsuggett
Contributor II

Ok... Sorry... I've try copying out the syntax and its not working... Its missing a characters and such... will try a link or something

bsuggett
Contributor II

Please be kind... I'm not a shell scripter... I'm a powershell scripter.... So there might be formatting issues all over the place... but it works and displays in the logs really nicely...

bsuggett
Contributor II

bsuggett
Contributor II
#!/bin/sh
echo
####################################################################################################
# SCRIPT CREATOR: JAMF nation user: bsuggett
# SCRIPT LAST MODIFIED BY: JAMF nation user: bsuggett
# Company I Work 4
#
# References:
# Some code has been borrowed from JAMF Software's scripts.
####################################################################################################

##############################################################################
# VARIABLES USED BY SCRIPT
##############################################################################

MachineSerial="`system_profiler SPHardwareDataType | grep "Serial Number" | awk '{ print $4 }'`"

if [ "$1" != "" ] && [ "$targetDrive" == "" ]; then
    targetDrive="$1"
fi

if [ "$2" != "" ] && [ "$computerName" == "" ]; then
    computerName="$2"
fi

if [ "$3" != "" ] && [ "$userName" == "" ]; then
    userName="$3"
fi

# Distribution point string to search for in /Volumes directory
if [ "$4" != "" ] && [ "$DistributionPoint" == "" ]; then
    DistributionPoint="$4"
fi

# Source Path excluding /Volumes/Mount 
if [ "$5" != "" ] && [ "$SourcePathOnDP" == "" ]; then
    SourcePathOnDP="$5"
fi

# Source File on DP, if left EMPTY will use MachineSerial
if [ "$6" != "" ] && [ "$SourceFile" == "" ]; then
    SourceFile="$6"
fi

# Path to place file locally
if [ "$7" != "" ] && [ "$DestinationFilePath" == "" ]; then
    DestinationFilePath="$7"
fi

# Destination file name
if [ "$8" != "" ] && [ "$DestinationFile" == "" ]; then
    DestinationFile="$8"
fi

# Destination file permissions. eg 775
if [ "$9" != "" ] && [ "$DestinationFilePermission" == "" ]; then
    DestinationFilePermission="$9"
fi

####################################################################################################
# CHECK MANDATORY PARAMETERS HAVE VALUES ASSIGNED 4, 5, 7, 8. 6 Uses MACHINE SERIAL NO IF EMPTY
####################################################################################################
echo
echo "Checking parsed parameters..."

if [ -n "$4" ]; then
    echo "Parameter 4 declared... : $4"
else
    echo "Parameter 4 empty! : Please assign a string to search for."
    exit 1      ## Failure
fi

if [ -n "$5" ]; then
    echo "Parameter 5 declared... : $5"
else
    echo "Parameter 5 empty! : Please assign a path to the file."
    exit 1      ## Failure
fi

if [ -n "$6" ]; then
    echo "Parameter 6 declared... : $6"
else
    SourceFile="$MachineSerial"
    echo "Parameter 6 empty... Using machines serial number... : $SourceFile"
fi

if [ -n "$7" ]; then
    echo "Parameter 7 declared... : $7"
else
    echo "Parameter 7 empty! : Please assign a destination path."
    exit 1      ## Failure
fi

if [ -n "$8" ]; then
    echo "Parameter 8 declared... : $8"
else
    echo "Parameter 8 empty! : Please assign a destination file."
    exit 1      ## Failure
fi

if [ -n "$9" ]; then
    echo "Parameter 9 declared... : $9"
else
    echo "Parameter 9 empty... File permission won't be changed. Only ROOT has access."
fi
echo

##############################################################################
# SEARCHING 4 MOUNTED DISTRIBUTION POINT STRING DECLARED IN PARAMETER 4
##############################################################################
echo "Searching /Volumes for current distribution point..."

CurrentDP="` ls /Volumes/ | grep -i "$DistributionPoint" -m 1`"
if [ -z $CurrentDP ]; then
    echo "Error, Distribution point not found"
    exit 1      ## Failure
else
    echo "Found... Distribution point is $CurrentDP"
fi
echo
##############################################################################
# SEARCHING FOR FILE ON DISTRIBUTION POINT DECLARED IN PARAMETER 5 AND PARAMETER 6
##############################################################################
echo "Verifying file exist on distribution point..."
if [ ! -f "/Volumes/$CurrentDP$SourcePathOnDP$SourceFile" ]; then
    echo "/Volumes/$CurrentDP$SourcePathOnDP$SourceFile"
    echo "Error, File not found"
    exit 1      ## Failure
else
    echo "Found... /Volumes/$CurrentDP$SourcePathOnDP$SourceFile"
fi
echo
##############################################################################
# COPY FILE FROM DP TO LOCAL MACHINE DECLARED IN PARAMETER 7 AND PARAMETER 8
##############################################################################
echo "Copying file from distribution point to local machine..."
echo "Destination... $DestinationFilePath$DestinationFile"

cp -f "/Volumes/$CurrentDP$SourcePathOnDP$SourceFile" "$DestinationFilePath$DestinationFile"

echo
##############################################################################
# CHECK COPIED FILE EXISTS ON LOCAL MACHINE
##############################################################################
echo "Checking copied file exists..."
if [ ! -f "$DestinationFilePath$DestinationFile" ]; then
    echo "Error, File not found"
    exit 1      ## Failure
else
    echo "Found... $DestinationFilePath$DestinationFile"
fi
echo

##############################################################################
# CHANGE FILE PERMISSION ON FILE TO PARAMETER 9 IF DECLARED
##############################################################################
echo "Destination File Permission"
if [ -n "$9" ]; then
    echo "Changing file permission on : $DestinationFile"
    echo "Permissions : $DestinationFilePermission"
    chmod $DestinationFilePermission "$DestinationFilePath$DestinationFile"
else
    echo "Parameter 9 empty... File permission won't be changed. Only ROOT has access."
fi

#######################################
# FINISHED
#######################################

exit 0      ## Success

msnowdon
Contributor

Hi,

I have a similar question but should be much easier. I'm creating a policy to push out Sibelius 8. This is the stand alone version but would like to find a terminal command to activate it once installed. Otherwise a user with the key and administrative permissions would need to activate it.