Maximum number of processes

If you’re with some Linux background under you belt then probably the first command you would think about is ulimit -a. The same command exists under Solaris

root@root # ulimit -a
core file size        (blocks, -c) unlimited
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
open files                    (-n) 32768
pipe size          (512 bytes, -p) 10
stack size            (kbytes, -s) 8192
cpu time             (seconds, -t) unlimited
max user processes            (-u) 19995
virtual memory        (kbytes, -v) unlimited

But there is a small difference. Whilst under Linux you are free to use it to change the maximum number of processes available to a single user, under Solaris it won’t work complaining:

ulimit: max user processes: cannot modify limit: Invalid argument

So what’s next? Remember that the maximum size of the process table depends on the total amount of physical memory installed in the system. This dependance is reflected in internal variable, called maxusers, and is determined at boot time.

#define MAX_MAXUSERS  4096u

if (maxusers == 0) {
      pgcnt_t physmegs = physmem >> (20 - PAGESHIFT);
      pgcnt_t virtmegs = vmem_size(heap_arena, VMEM_FREE) >> 20;
      maxusers = MIN(MAX(MIN(physmegs, virtmegs),

OpenSolaris source code

It is also used to set two other kernel variables: max_nprocs and maxuprc to describe the maximum number of process systemwide and the maximum number of processes an ordinary user can have respectively.

if (max_nprocs == 0)
     max_nprocs = (10 + 16 * maxusers);
if (platform_max_nprocs > 0 && max_nprocs > platform_max_nprocs)
     max_nprocs = platform_max_nprocs;
if (max_nprocs > maxpid)
     max_nprocs = maxpid;
if (maxuprc == 0)
     maxuprc = (max_nprocs - reserved_procs);

OpenSolaris source code

To display the current values form the console just run mdb to explorer these variables:

> maxusers/D
maxusers:       2048

> max_nprocs/D
max_nprocs:     20000

> maxuprc/D
maxuprc:        19995

To set the maximum number of processes a non-root user could have just update maxuprc value through either mdb or /etc/system file. Keep in mind that:

  • maxuprc must be less than max_nprocs
  • If you want to make your settings permanent across the reboots – use /etc/system file.

Whilst what I’ve said here is true both for Solaris 9 and 10 in Solaris 10 using “Resource Management” you could create more refined constrains to define the way a user can run his/her processes.

No way I want to make the same mistakes again

To avoid stepping on the same rake again and to fix the issue described in this post, I came out with a simple expect script to save current configuration of Qlogic Sanbox switches.

#!/usr/local/bin/expect -f

set switches "switch1 switch2"
set user {user}
set pass {pass}
set ftp_user {ftp_user}
set ftp_pass {ftp_pass}
set timeout 10
log_user 0
set prompt "(%|#|\\$) $"
catch {set prompt $env(EXPECT_PROMPT)}

set sec [clock seconds]
set date [clock format $sec -format %d%m%Y]

set back [clock add $sec -7 days]
set bdate [clock format $back -format %d%m%Y]

for {set x 0} {$x<[llength $switches]} {incr x} {

set current_switch [lindex $switches $x]

spawn telnet $current_switch

expect {
        timeout {puts "timeout while connecting to $host"; exit 1}
send "$user\r"

expect {
        timeout {puts "timed out waiting for the password prompt"; exit 1}
send "$pass\r"

expect {
        timeout {puts "timed out after login"; exit 1}
send "admin start\r"

expect {
        timeout {puts "timed out waiting for admin mode"; exit 1}
        "(admin) #>"
send "config backup\r"

expect {
        "(admin) #>"
send "admin end\r"

expect {
send "quit\r"

spawn ftp sanbox4
expect {
        timeout {puts "timed out waiting for ftp login request"; exit 1}
send "$ftp_user\r"

expect {
        timeout {puts "timed out waiting fro ftp password request"; exit 1}
send "$ftp_pass\r"

expect {
        timeout {puts "timed out waiting for ftp prompt"; exit 1}
send "get configdata /pth_to_backup_directory/configdata_$current_switch-$date\r"
expect "ftp>"
send "quit\r"

if {[file exists /path_to_backup_directory/configdata_$current_switch-$bdate]} {
        exec /usr/bin/rm /path_to_backup_directory/configdata_$current_switch-$bdate


We all know how incredible and flexible sed really is and recently I had another chance to experience its coolness in the field when one of our Qlogic Sanbox switch lost zone configuration completely. So obvious solution in such cases is just to restore from the backups but since it wasn’t possible, it’s a shame but there weren’t any on my hands, I simply restored zones information from another switch in the same fabric. That worked nicely with one drawback – lack of alias information. Luckily we had an old zone backup with aliases that could be used to restore the missing part of our configuration. Nevertheless, the information in that file was a bit outdated but in our situation it was better than nothing. From the inside the file I needed to parse had the following structure:

<ZoneAlias name="zone_name1">
<ZoneAlias name="zone_name2">

So to parse it to the format required by the switch I wrote a simple sed script that saved me from doing a monkey’s job and restoring everything manually:

for zn in `cat zoneset_with_alias.xml | \
sed -n ‘/<ZoneAlias/,/<\/ZoneAlias>/ s/.*name=\”\(.*\)\”.*/\1/p’`; \
do for m in `cat zoneset_with_alias.xml | \
sed -n ‘/<ZoneAlias name=”‘$zn'”/,/<\/ZoneAlias>/ p’ | \
sed -n ‘/<ZoneAliasMember>/,/<\/ZoneAliasMember>/ s/.*[a-z][0-9].*/&/p’`; \
do echo -n “$zn “; echo $m | \
sed ‘s/[0-9a-zA-Z][0-9a-zA-Z]/:&/g’ |sed ‘s/^://’; done; done

P.S. Frankly speaking, I spent more time writing this note than the script itself.


No matter how hard I’d tried but I eventually caught cold. Nasty filling, running nose and a sore throat that’s what I will have to live with for the next couple of days. Btw, what a marvelous installation I created to today from the tissues on my desk – I definitely should’ve taken a picture of it ;-). 

Just another rainy day

Something is just not right – the more you’re longing for a weekend the more chances it won’t come about the way you covet it.  Thanks God every cloud has a sliver lining so we stopped whining to no purpose and bent our steps toward the Museum of Paleontology, a place I’ve been to only once and it was long time ago and, frankly speaking, never thought about coming there again, very unwise, but since my son is yet to discover the outward things it was the best choice of the Saturday’s morning. 

At 9 a.m. almost no traffic, so we happily reached the place in less than 40 minutes, bought the tickets and traveled hundreds of millions years back into the past. Very ineffable fillings. Old bones, fossils, mammoths’ and dinosaurs’ models just in a second made our “the hub of the universe” like behavior fallacious. Thrilling… But of course not for my boy who is capable to turn any place into a playground and tune it up to his child’s vision of the world. 
The rest of the day, after we made a short brake, was no less interesting and cognitive for we went to Moscow aquarium and spent some time there admiring the underwater world: morays, jelly fish, turtles, king crabs, sharks, etc. etc. etc. It’s not one of the world-class huge ocean aquariums but a cramped basement where home fish hobbyist could purchase stuff for their fish bowls whilst the rest just admire numerous kinds of underwater elements. That’s why I found this place a bit overpriced but still it’s the best one in Moscow region. 

The die is cast

Just wandering if I could treat my the very first post as the very first step (though a virtual on) even if I still don’t know in what direction I’m going to and most noteworthy what it could bring about later. Anyway, let’s keep it short as with everything we do for the first time to diminish the possibility of an inadvertent mistakes.