Questions
and Answers
Q My Ultra 10 box running Solaris
7 is a JumpStart server with a Solaris 8 01/00 release image on
it. I want the latest features of Solaris, though, so I downloaded
the maintenance upgrade (MU) from SunSolve. Can I "patch" my JumpStart
image as I originally intended? If so, how? The install_mu
shell script was obviously intended to upgrade a running OS, and
I see nothing in the accompanying documentation of any relevance
to upgrading a JumpStart image.
A No, you cannot easily patch the
JumpStart image on your disk. The maintenance updates are provided
as a series of patches to the base operating system. What you can
do is apply the maintenance update patches on each of your newly
jumpstarted machines using one of your post install scripts, just
like you would with the recommended patch set.
The best course of action, though, is to just install a new JumpStart
image from the latest ISO images instead of using the maintenance
updates. That way you'll have the new base OS instead of a patched
older base OS.
Q I'm creating a bash script that's
supposed to do things to people's home directories. Root runs this
script and gives the username as an argument on the command line.
In the script, I'm trying to use ~username to access the
user's home directory like this:
#!/usr/local/bin/bash
ls ~$1
Instead of seeing the contents of the user's directory, I get the
output:
ls: ~username: No such file or directory
Where "username" is the argument that was passed in to the script.
If I hardcode the script, everything works fine:
#!/usr/local/bin/bash
ls ~username
Why isn't it working when I pass in the username, and why do I get
an error saying that it can't find ~username when ~username
is clearly there and works when it's hardcoded? How can I make this
work so I can operate on user's home directories?
A The reason that your script is
not working is because of the order of expansion. There are two
different items being expanded: ~ and $1. The ~
is expanded first, and then your script tries to do an ls
on the directory called, literally, ~$1. Obviously this doesn't
work, so your shell script goes to print out an error. When the
error is printed, however, the second expansion takes place and
$1 becomes the argument you passed in. To get around this,
you want to use eval:
#!/usr/local/bin/bash
eval "homedir=~$1"
ls $homedir
You can also use some other basic UNIX tools to accomplish the same
thing instead of using tilde expansion in your script (since not all
shells support tilde expansion). These next two command-line examples
assume that your password file contains all of the local users (no
NIS/NIS+/LDAP or other remote account authorization in use) and that
the user's home directory is stored in the sixth field of the password
file:
awk -F: '/^username:/ {system("ls "$6)}' /etc/passwd
grep ^username: /etc/passwd | cut -d: -f6 | xargs ls
You can also take a similar approach but substitute checking /etc/passwd
with checking NIS maps or LDAP output, too. Be sure to make it so
that the string match on the username will be unique. In the case
of checking /etc/passwd, the username will be the first field
of output, immediately followed by a ":".
The other caveat to changing things based on the user's home directory
is that you may have some users that have invalid home directories,
system directories, or files as home directories, or share home
directories with other users. For example, be on the look out for
home directories such as:
/
/dev/null
/nohome
/tmp
You don't want to blindly change things in places such as those.
Q I made some modifications to /etc/system
to tune the kernel. I am running Sun OS 5.8, and I added the following
lines:
set shmsys:shminfo_shmmax = 4294967295
set shmsys:shminfo_shmmin = 1
set shmsys:shminfo_shmmini = 100
set shmsys:shminfo_shmseg = 100
set shmsys:seminfo_semmni = 100
set shmsys:seminfo_semmsl = 510
set shmsys:seminfo_semmns = 1010
set shmsys:seminfo_semopm = 100
set shmsys:seminfo_semvmx = 32767
set shmsys:seminfo_semume = 30
I then rebooted the server as stated in the manual. I also did a boot
-r from the OK prompt just in case. However, I received the following
errors when the machine booted:
Jul 12 14:56:52 host.domain.com genunix: [ID 492708 kern.notice] sorry,
variable 'shminfo_shmmini' is not defined in the 'shmsys'
Jul 12 14:56:52 host.domain.com genunix: [ID 966847 kern.notice] module
Jul 12 14:56:52 host.domain.com genunix: [ID 492708 kern.notice] sorry,
variable 'seminfo_semmni' is not defined in the 'shmsys'
Jul 12 14:56:52 host.domain.com genunix: [ID 966847 kern.notice] module
Jul 12 14:56:52 host.domain.com genunix: [ID 492708 kern.notice] sorry,
variable 'seminfo_semmsl' is not defined in the 'shmsys'
Jul 12 14:56:52 host.domain.com genunix: [ID 966847 kern.notice] module
Jul 12 14:56:52 host.domain.com genunix: [ID 492708 kern.notice] sorry,
variable 'seminfo_semmns' is not defined in the 'shmsys'
Jul 12 14:56:52 host.domain.com genunix: [ID 966847 kern.notice] module
Jul 12 14:56:52 host.domain.com genunix: [ID 492708 kern.notice] sorry,
variable 'seminfo_semopm' is not defined in the 'shmsys'
Jul 12 14:56:52 host.domain.com genunix: [ID 966847 kern.notice] module
Jul 12 14:56:52 host.domain.com genunix: [ID 492708 kern.notice] sorry,
variable 'seminfo_semvmx' is not defined in the 'shmsys'
Jul 12 14:56:52 host.domain.com genunix: [ID 966847 kern.notice] module
Jul 12 14:56:52 host.domain.com genunix: [ID 492708 kern.notice] sorry,
variable 'seminfo_semume' is not defined in the 'shmsys'
Jul 12 14:56:52 host.domain.com genunix: [ID 966847 kern.notice] module
Why am I getting these errors? Can I ignore them, or is something
broken?
A You have the wrong variables
and modules. Take a look at System V Semaphores and System V Shared
Memory under:
http://docs.sun.com/ab2/coll.736.2/SOLTUNEPARAMREF/@Ab2PageView/1220
There is no shminfo_shmmini (perhaps you meant shminfo_shmmni,
whose default is already 100), and all of the seminfo variables you
list belong under the module semsys, not shmsys. Try this instead:
set shmsys:shminfo_shmmax = 4294967295
set shmsys:shminfo_shmmin = 1
set shmsys:shminfo_shmmni = 100
set shmsys:shminfo_shmseg = 100
set semsys:seminfo_semmni = 100
set semsys:seminfo_semmsl = 510
set semsys:seminfo_semmns = 1010
set semsys:seminfo_semopm = 100
set semsys:seminfo_semvmx = 32767
set semsys:seminfo_semume = 30
Q I'm writing a Bourne shell
script that needs to read in a username and shell as arguments, instead
of prompting the user for input while the script is running. The order
of the parameters shouldn't matter, and I want to make this extensible
so that I can add other command-line options in the future. What's
the best way to do this, a for loop, a while loop, if
statements?
A You can certainly do what you
want with a plain while loop, as in the following:
#!/bin/sh
while [ $# -gt 0 ]
do
case "$1" in
-u) USERNAME=$2;;
-s) USERSHELL=$2;;
esac
shift
done
echo "user == $USERNAME"
echo "shell == $USERSHELL"
Even better, though, is to use getopts to specify your options:
#!/bin/sh
while getopts u:s: opt
do
case "${opt}" in
u) USERNAME=${OPTARG}
;;
s) USERSHELL=${OPTARG}
;;
esac
done
shift 'expr ${OPTIND} - 1'
echo "user == ${USERNAME}"
echo "shell == ${USERSHELL}"
Be sure to do some error checking to verify that you actually have
a valid value for each variable before you try to use it, though.
The options that getopts is aware of in this case are u:s:.
The ":" after each letter option means that an argument is required.
If you leave out the ":", then the flag can stand on its own without
an argument. The space between the flag and the argument is optional.
You can invoke this script in either of these ways:
./script -u User -s Shell
./script -uUser -sShell
When getopts finds a valid flag, it puts the associated argument,
if any, into the variable OPTARG. The variable OPTIND
contains the pointer to the current word.
For each iteration through the while loop, getopts
looks for a valid command line flag (u or s, in this
case) and then uses a case statement to decide on the action. If
you used -u, then the action is to assign the argument (stored
in OPTARG) to the variable USERNAME. If it's -s,
you store the value in USERSHELL. You then decrement OPTIND
and look for the next valid option. When working with your own variables
for usernames and shells, be sure not to use the environment variables
${USER} and ${SHELL} or you may wind up with some
very unexpected results.
Amy Rich, president of the Boston-based Oceanwave Consulting,
Inc. (http://www.oceanwave.com), has been a UNIX systems
administrator for more than five years. She received a BSCS at Worcester
Polytechnic Institute, and can be reached at: arr@oceanwave.com.
|