Trying to create a script to run as root, permission denied

Hello all, I am trying to create a script or a .command file that will run for me and my other techs on many, many Mac OSX computers that will add a file to the /etc/ folder called /etc/launchd.conf

Every time I try to run the script, I get "Permission Denied" when trying to put the file into the /etc/ directory.

The reason for this script is we will need to deploy this script quickly across many Macs, and it will only be run by myself or other admins. We just want to make it easier for us so we do not have to manually go to the /etc/ folder and create the launchd.conf file each time. I dont mind having to type in the root password at launch of this script, but I would prefer to not have to type in the root password each time...i would love it if this could be completely autonomous.

here are the two versions of code that I have tried so far, based on help from other Google inquiries:

#!/bin/bash

clear ; echo This script will put a system configuration file into your Mac OSX that will assist with UNIX permissions on the IFS

clear ; 
echo Moving Working Directory to the System Directory
cd /etc/

echo Creating a new file with correct permissions, please have system root password ready...

sudo cat <<EOF >> launchd.conf
umask 000
EOF
echo Process has completed, thank you. 

and this:

#!/bin/bash

clear ; echo This script will put a system configuration file into your Mac OSX that will assist with UNIX permissions on the IFS
sleep 2
clear ; 

chown root Test3.command
chmod u+s Test3.command

echo Moving Working Directory to the System Directory
cd /etc/
sleep 2
echo Creating a new file with correct permissions, please have system root password ready...
sleep 3
sudo cat <<EOF > launchd.conf
umask 000
EOF
echo Process has completed, thank you. 
sleep 2

Does anyone know how I can create this script for us to run?
Thank you very much.

What if you create a different directory where you and the other sysadmins have write permission, have the script create the file in that different directory, and make /etc/launchd.conf a symbolic link to the file created in that different directory?

How would we create the symbolic link? Wouldn't there have to be permissions to put that link in the /etc/directory?

I'm very new to UNIX, so I dont know hardly anything. Most of that code I put in my first post was found off of Google.

---------- Post updated at 01:40 PM ---------- Previous update was at 01:22 PM ----------

I just tried that, and I still got the "Permission Denied" when trying to put the link into the /etc/launchd.conf

#!/bin/bash

echo Moving Directories

cd /Users/jlemme2/Desktop

sudo cat <<EOF >> launchd.conf
umask 000
EOF

ln -s /Users/jlemme2/Desktop/launchd.conf /etc/launchd.conf

echo Process Completed

Any other ideas?

Don't put the ln command in the shell script. It doesn't work in the shell script because of the same permissions problem.

The ln command only needs to be run once, as root, outside the shell script:

# ln -s /Users/jlemme2/Desktop/launchd.conf /etc/launchd.conf

Then, whenever you want, run the script to create /Users/jlemme2/Desktop/launchd.conf which you have write permission to create.

oh ok, I see what you are saying now. I will try that out.
I also have another way I am investigating now.
What I seem to have found is I can create one script that runs my second script as sudo (root), I am just trying to get it to be able to *find* that second script (like if I place both in a USB stick, how do i tell the terminal window to look in that same directory to find the second script.
When I ran my first script from the terminal command line as root, the script worked...that's why i created a second script to simply run my first as root.

here is what I have:

First Script: (Test3.command)

#!/bin/bash

clear ; echo This script will put a system configuration file into your Mac OSX that will assist with UNIX permissions on the IFS

clear ; 
echo Moving Working Directory to the System Directory
cd /etc/

echo Creating a new file with correct permissions, please have system root password ready...

sudo cat <<EOF >> launchd.conf
umask 000
EOF
echo Process has completed, thank you. 

Second Script:

#!/bin/bash

sudo .~/Test3.command

How can I tell Mac OSX to look at the same directory that both scripts are in to run it? When I run the second script now, I get this output:

Last login: Thu Apr 11 14:04:12 on ttys001
XXXX-MacBookPro:~ jlemme2$ /Users/jlemme2/Desktop/ifs/Test6.command ; exit;
Password:
sudo: .~/Test3.command: command not found
logout

[Process completed]

And, as a second part, how would I combine these two scripts into one, if it was possible?
I am also researching myself, so if I figure out my own answer I will post it here. I do appreciate your assistance with this.

AFAIK, .~/Test3.command does not have a clear meaning.

. means current directory.
~ means home directory.

I don't think it makes sense to put them together, unless there is something I'm missing (always possible). Use . or ~ depending on the intent, but not both.

-------------------

To find the second script, you either need an absolute or relative path to the second script, or the second script needs to live in a directory that is in the PATH variable.

Did the script stuff run from your shell prompt, interactively? Who or what calls the script (and has to provide environment): cron, ssh, webserver, ???

no, you are right...I am a total newbie to UNIX, so I didn't know.

How would I write this script to tell the script to run the second script which is located in the same directory as the first? (sorry if confusing)

Ex. If I put both of these files on a USB stick and plugged it into a Mac and ran this script. Where does Mac mount the USB at by default? /dev/???

---------- Post updated at 03:11 PM ---------- Previous update was at 03:07 PM ----------

Not quite sure what you mean by this...sorry.
I would just put these files on a USB, then double click on the first script, which would authenticate as root and then call the second script. Is that what you are talking about?

Don't get too hackeresque, we seen that movie. When you plug a usb drive into a system, it can be automounted and some systems like windows can autorun things on it. Not being a mac hacker, I am not sure how to set up either.

Once it is mounted, for any script run, its location will discernable from $0 and $PWD, and possibly $PATH, as the only way to run it is with an absolute path, a relative path or a $PATH dir entry. The apparent script location may not be a real path, if it was run through a symbolic link, but you can run realpath to find out or chain up .. until root (inode .. = inode . )

In a unix file system:

  1. there are many types of inode: directory, flat file, symbolic link, named pipe, raw device, cooked device and maybe a few I forget. Read the source, Luke, and man pages, too.
  2. A directory is essentially a list of entry names and their inode numbers -- nothing else!
  3. The inode numbers are relative to the device.
  4. The root tree starts on the root device, but you can mount file systems over directories, hiding those directories and all that might be in them on the parent device, and establishing another device for that sub-tree. You can see some oddities in such a neighborhood in the ., .., directory's entry name inode numbers, as I recall. df and mount show you all the mount points including root, read off root!
  5. One device can be mounted upon another.
  6. Some variations of ls and find show inode numbers and device numbers.
  7. A symbolic or soft link contains a path, relative or absolute, to a replacement entry. The ln command creates both
  8. hard links (two directory entries with the same inode #, like /. and /..) and symbolic or soft links or sym-links (-s), rather like windows shortcut file *.lnk.
  9. The rm command is a wrapper for unlink(), as a file is not really removed until all links, directory entries to the inode, are destroyed (the inode has a count, which you see on ls -l), and even then the inode is parked somewhere like lost and found if it is still open at remove time. SOme tolls remove temp files after openeing them, so there is never any collision of names, cleanup, prying or interference.
  10. Only the system can hard link directories (every child directory's .. is another link on the parent directory inode, plus . and its entry in the grandparent), so symbolic links on directories are very popular. Not sure offhand about hard links on other inodes! Windows NTFS allows hard links, too, which I noticed under CygWin just recently! I am not sure if Mozy double-charges me to back them up! :smiley:
  11. If I use a symbolic link, find -type f ill miss it unless I say -follow. The ls option L makes it punch through sym-links. Using a trailing / or /. forces a trip through to the real inode, too.
  12. NFS and its buddies can mount remote files in the local tree. All calls just wander over to the real system on the net.
  13. Traditional simple file systems are initially configured with just so many inodes on the device, and you can run out.
  14. Complex file systems can be runing interference behind the facade to make many devices into one, slide space from one place to another, add ACLs for extended permissioning, mirror, RAID, quota, .... They can manufacture inodes on demand. They can make for a slow reboot from any ungraceful shutdown, too. SAN systems may use NFS or have proprietary connection hardware and protocols. Solaris Client file systems can use local disk space as a persistent cache for NFS mounts. And so the head starts spinning.
  15. Welcome to UNIX file land.
1 Like

Haha, sorry I am not trying to be a hacker.
I ended up finding out what I need to make this work. It's not perfect by any means, but it gets the job done for what I am looking for. If anyone knows how to put these two scripts into one, that I could just double click on when I copy it to the desktop of any computer, that would be awesome, otherwise I think I am good to go.

First script logs me in as root, and then calls the second script to run.

ClickMe.command

#!/bin/bash
clear;
sudo Desktop/ifs/IFS_Perm.command

IFS_Perm.command

#!/bin/bash

clear ; echo This script will put a system configuration file into your Mac OSX that will assist with UNIX permissions on the IFS
sleep 2
clear ; 
echo Moving Working Directory to the System Directory
cd /etc/
sleep 2
echo Creating a new file with correct permissions, please have system root password ready...
sleep 3
sudo cat <<EOF >> launchd.conf
umask 000
EOF
echo Process has completed, thank you. 
sleep 3
killall Terminal

exit 0

Thanks all for your help, and thank you DGPickett for your lenghty, informative information!

Typically, I just press the command+u key combination, launch the terminal, type sudo followed by a space, then drag the desired script to the terminal window.

For double click simplicity, I will usually create a "payload free" package that runs the script as a preinstall script. This also has the advantage of being deployable through a wide variety of remote management products. You don't have to train field techs how to use the terminal either. :wink:

It all makes more sense if you know a little about what is underneath. It is pretty simple, really, but as Einstein said, 'not too simple', in this case, to be useful and versatile. It's like remembering that all the nice stuff on your screen is one pixel deep (unless you have an old ti pc) and represents the last repaint.

This command does not do what you think it does:

sudo cat <<EOF >> launchd.conf
umask 000
EOF

Let me explain in detail the order which it does these things.

  • Redirects 'umask 000' into stdin
  • Redirects stdout into launchd.conf
  • Forks and executes 'sudo cat', letting it inherit these I/O redirections

You see the problem? It opens the files before it runs sudo. It has to -- you can't alter stdin and stdout for a program that's already running, you have to set them up first. By the time you call sudo, your shell has already tried and failed to open the file.

You have to run all that code inside sudo, since sudo is the thing with elevated permissions.

sudo bash <<EOF
        echo "umask 000" >> launchd.conf
EOF

I'd think you'd need:

sudo bash -c '
cat <<EOF >> launchd.conf
umask 000
EOF
'