# How to set ulimits for a service starting at boot?

I need, for mysql to use large-pages, to set a ulimit - I've done this in limits.conf. However, limits.conf (pam_limits.so), doesn't get read in for init, only for "real" shells. I solved this before by adding a "ulimit -l" to the initscript start function. I need some sort of repeatable way to do this, now that the boxes are managed with chef, and we don't want to take over a file that's actually owned by the RPM.

-
Please have a look to see if you are hitting the same bug. serverfault.com/questions/415570/… –  Minto Joseph Oct 6 '12 at 4:24

Not sure of how distro-specific this is, but I have just incorporated a security limit increase by using /etc/security/limits.d/20-somefile.conf in Ubuntu.

Rather than having to modify an existing file, I have an ERB template in my cookbook, set default attributes in an attributes file and then don't have to worry about using ruby blocks with "insert_line_if_no_match" stuff - that seems a little more intricate and the recipe is a bit more readable like this:

execute "activate_sysctl" do
user "root"
command "sysctl -p /etc/sysctl.d/10-filemax.conf"
action :nothing
end

template "/etc/sysctl.d/10-filemax.conf" do
source "system/filemax.conf"
action :create
notifies :run, "execute[activate_sysctl]", :immediately
end


and then this is my template file:

fs.filemax = <%= node[:mycookbook][:system_fs_filemax] %>

-

Self-contained recipe snippet based on this url:

http://pro.benjaminste.in/post/318453669/increase-the-number-of-file-descriptors-on-centos-


Recipe Snippet:

ruby_block "edit /etc/sysctl.conf" do
_file = "/etc/sysctl.conf"
_comment = "# TWEAK BY CHEF"
_content = "fs.file-max = 512000"
block do
file = Chef::Util::FileEdit.new(_file)
file.insert_line_if_no_match(/#{Regexp.escape(_comment)}/, "#{_comment}\n#{_content}")
file.write_file
end
not_if "cat #{_file} | grep '#{_comment}'"
notifies :run, "execute[sysctl -p]", :immediately
end

execute "sysctl -p" do
command "sysctl -p"
returns 255 # which would normally signify error, but doesn't on sysctl on CentOS
action :nothing
end

ruby_block "edit /etc/security/limits.conf" do
_file = "/etc/security/limits.conf"
_comment = "# TWEAK BY CHEF"
_content = "* - nofile 65535"
block do
file = Chef::Util::FileEdit.new(_file)
file.insert_line_if_no_match(/#{Regexp.escape(_comment)}/, "#{_comment}\n#{_content}")
file.write_file
end
not_if "cat #{_file} | grep '#{_comment}'"
end

-

My solution was simply doing this in our chef recipe:

# Ensure ulimits are properly set for the initscript
bash "Set Ulimits" do
user "root"
code <<-EOH
echo -e "n#Setting ulimits. Performed by chef recipe MYSQLULIMIT\nulimit -l" >> /etc/sysconfig/init
EOH
not_if "grep MYSQLULIMIT /etc/sysconfig/init"
end


This causes the ulimit -l to get set for all initscripts, which may be undesirable in some environments, but is fine for mine.

In a perfect world, I'd get the RPM updated to include a /etc/sysconfig/mysqld, and put the same ulimit -l command in there.

-

/etc/sysctl.conf should be able to set the ulimits items. I've not been able to test this well but survey says you should be able to stop after it's set in sysctl.conf.

I've found various topics that show it's still a problem though and my team and I have discussed some options around this we have found two potential workarounds.

Option 1: Most rhel initscripts source /etc/init.d/functions, you could change the ulimit settings there

Option 2: init claims that /etc/initscript is sourced everytime before init spawns whatever see: http://linux.die.net/man/5/initscript. Interestingly enough they say its where people can set ulimit =)

-

echo "* hard nofile 102400" >> /etc/security/limits.conf

echo "* soft nofile 102400" >> /etc/security/limits.conf

sysctl -w fs.file-max=102400

sysctl -p

The 4 steps can change your system's limits immediately, and can still work after your reboot. You can change the number "102400" to the number of max open-file in your linux system as you want. and

sysctl -p

to load in sysctl settings from the file specified or /etc/sysctl.conf if none given.

-
limits.conf is not read by inittab because limit.so is not read for it. You might be able to hack PAM but I cant figure out which file it might read. –  Xarses Jul 17 '12 at 4:10

I actually wrote a private chef cookbook that is used to set ulimit for us and it works pretty well. For ubuntu we found the following trick is required if you want a global ulimit setting:

session required        pam_limits.so


and in limit.conf you must have the following:

* soft  nofile  64000
* hard  nofile  65000

root  soft  nofile  64000
root  hard  nofile  65000


The root part is important as it seems without that some init script will not work correctly. So we have a chef cookbook that setup the following and it works great.

Another option we used to use for Tomcat was to deploy Tomcat and then overwrite the init script with a custom which we would set the ulimit for and restart tomcat. This works great but is a bit more hacky then the first.

I hope this help, and maybe someday I can opensource the cookbook we have internally since its pretty dead simple but might be helpful to others like you.

-
This wont solve the poster's issue. Pam is only invoked when a user opens a session (shell). Since the init system is started independently of user sessions, pam does not apply. –  Patrick Mar 31 '12 at 5:39

Try setting that up in /etc/sysctl.conf file

-
There are pieces of configuration required to do this that belong in sysctl.conf, and those are in place -- we just need to modify ulimits to allow those hugepages to be accessed. –  jayofdoom Mar 29 '12 at 14:29