Module: Doable::Helpers::Linux
- Includes:
- Exceptions::Linux, OS
- Defined in:
- lib/doable/helpers/linux.rb
Instance Method Summary collapse
-
#add_bashrc_entry(user, entry) ⇒ Object
Add an entry to a user’s ~/.bashrc.
-
#apply_patch(options, patch_file, path = nil, user = nil) ⇒ Object
Apply a patch file.
-
#check_disk_space(directory, min_space) ⇒ Object
Finds the mount point for a directory, then checks it for a minimum number of kilobytes.
-
#check_for_rpms(rpms) ⇒ Object
Check for RPMs (kind of RHEL / SuSE specific) #return [Boolean].
-
#chmod(permission, file_list, options = {recursive: false}) ⇒ Object
Used like Unix chmod.
-
#chown(user, group, file_list, options = {recursive: false}) ⇒ Object
Used like Unix chown.
-
#find_executable(name) ⇒ Object
Require an executable to be in $PATH.
-
#find_or_create_group(group) ⇒ Boolean
Ensure a group exists.
-
#find_or_create_user(user, homedir, options = {}) ⇒ Boolean
Ensure a user exists on the system.
-
#find_processes(regex) ⇒ Array<String>
Get a list of process matching a Regexp.
-
#find_user(user, noisy = false) ⇒ Array
Die if a user doesn’t exist.
-
#have_executable?(name) ⇒ String, false
Does the system have an executable in $PATH? If not, return false.
-
#kill(pid, signal = "TERM") ⇒ Object
Kill a process.
-
#run_as_user(user, command) ⇒ Object
Linux specific way to run something as another user.
-
#set_nofile(user, limit) ⇒ Boolean
Set the max number of open files for a user (nofiles) (sets both hard and soft, errors out if user is already listed in limits.conf) Currently does NOT verify the existence of the specified user on the system.
-
#set_user_password(user, new_pass) ⇒ Boolean
Sets a user’s password.
-
#update_user_gid(user, gid) ⇒ Object
Set a user’s gid (default group).
Methods included from OS
#die_if_dir_exists, #find_directory, #find_file, #find_or_create_directory, #find_or_create_file, #must_run_as, #remove, #sed, #tee, #touch, #validate_host
Instance Method Details
#add_bashrc_entry(user, entry) ⇒ Object
Add an entry to a user’s ~/.bashrc
58 59 60 |
# File 'lib/doable/helpers/linux.rb', line 58 def add_bashrc_entry(user, entry) File.open(File.("~#{user}/.bashrc"), "a") {|f| f.puts entry } end |
#apply_patch(options, patch_file, path = nil, user = nil) ⇒ Object
Apply a patch file
41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/doable/helpers/linux.rb', line 41 def apply_patch(, patch_file, path = nil, user = nil) cmd = "patch #{options} < #{patch_file}" olddir = `pwd`.chomp Dir.chdir(path) if path tee 'pwd' if user run_as_user user, cmd else tee cmd end Dir.chdir(olddir) if path end |
#check_disk_space(directory, min_space) ⇒ Object
Finds the mount point for a directory, then checks it for a minimum number of kilobytes
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/doable/helpers/linux.rb', line 224 def check_disk_space(directory, min_space) all_filesystems = `df -PB 1024`.chomp.split("\n").collect {|fs| fs.split if fs.match(/^\/dev/) }.compact best_fit = nil current_test = directory until best_fit matching_fs = all_filesystems.collect {|fs| fs if File.(fs[5]) == File.(current_test) }.compact if matching_fs.size == 1 best_fit = matching_fs.flatten else current_test = File.dirname(current_test) end end log "Closest matching filesystem is '#{best_fit[5]}'. Testing for free space..." if Integer(best_fit[3]) >= min_space log "Found sufficient space #{best_fit[3]} for install on #{best_fit[5]} with an install directory of #{install_dir}." else log "Insufficient space #{best_fit[3]} for install on #{best_fit[5]} with an install directory of #{install_dir}!", :error end end |
#check_for_rpms(rpms) ⇒ Object
Check for RPMs (kind of RHEL / SuSE specific) #return [Boolean]
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/doable/helpers/linux.rb', line 101 def check_for_rpms(rpms) raise InvalidRPMList unless rpms.kind_of?(Array) # Split the list of all installed RPMs into an Array containing only the RPM's base name system_rpms = `rpm -qa`.chomp.split("\n").collect {|rpm| rpm.split(/-[0-9]/)[0]} i686_rpms = `rpm -qa`.chomp.split("\n").collect {|rpm| rpm.split(/-[0-9]/)[0] if rpm.match(/\.i686$/)}.compact raise NotApplicable unless $?.success? missing_rpms = rpms.collect {|rpm| rpm unless rpm.match(/\.i686$/) }.compact - system_rpms # calculate what RPMs are not installed missing_rpms = (missing_rpms + (rpms.collect {|rpm| rpm.split('.')[0] if rpm.match(/\.i686$/) }.compact - i686_rpms).compact.map {|r| "#{r}.i686" } ).compact if missing_rpms.size > 0 log "Missing RPMs: #{missing_rpms.join(', ')}", :error raise MissingRPMs else return true end end |
#chmod(permission, file_list, options = {recursive: false}) ⇒ Object
Used like Unix chmod
26 27 28 29 30 31 32 33 34 |
# File 'lib/doable/helpers/linux.rb', line 26 def chmod(, file_list, = {recursive: false}) if [:recursive] .delete :recursive FileUtils.chmod_R(, file_list, ) else .delete(:recursive) if .has_key?(:recursive) FileUtils.chmod(, file_list, ) end end |
#chown(user, group, file_list, options = {recursive: false}) ⇒ Object
Used like Unix chown
13 14 15 16 17 18 19 20 21 |
# File 'lib/doable/helpers/linux.rb', line 13 def chown(user, group, file_list, = {recursive: false}) if [:recursive] .delete :recursive FileUtils.chown_R(user, group, file_list, ) else .delete(:recursive) if .has_key?(:recursive) FileUtils.chown(user, group, file_list, ) end end |
#find_executable(name) ⇒ Object
Require an executable to be in $PATH
91 92 93 |
# File 'lib/doable/helpers/linux.rb', line 91 def find_executable(name) have_executable?(name) ? true : raise(MissingExecutable, name) end |
#find_or_create_group(group) ⇒ Boolean
Ensure a group exists
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/doable/helpers/linux.rb', line 189 def find_or_create_group(group) all_groups = `getent group`.chomp.split("\n").map {|line| line.split(':')} this_group = all_groups.collect {|g| g if g[0] == group}.compact if this_group.size > 1 log "Multiple instances of group #{group} found. This is known to cause problems.", :error raise DuplicateGroups elsif this_group.size == 1 log "Group '#{group}' already exists with gid: #{this_group.flatten[2]}. Skipping creation of group...", :warn else log "Creating group '#{group}'..." `groupadd -r "#{group}"` raise FailedGroupAdd unless $?.success? return $?.success? end end |
#find_or_create_user(user, homedir, options = {}) ⇒ Boolean
Ensure a user exists on the system
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/doable/helpers/linux.rb', line 123 def find_or_create_user(user, homedir, = {}) # Create an Array of Arrays storing all known system users and their attributes all_users = `getent passwd`.chomp.split("\n").map {|line| line.split(':')} # Determine if the user we want exists this_user = all_users.collect {|u| u if u[0] == user}.compact if this_user.size > 1 log "Multiple instances of user #{user} found. This is known to cause problems.", :error raise DuplicateUsers elsif this_user.size == 1 log "User '#{user}' already exists with uid: #{this_user.flatten[2]}. Skipping creation of user...", :warn full_home = File.(homedir) current_home = File.(this_user.flatten[5]) if (full_home != current_home) and (homedir != current_home) log "User's home directory is set to #{current_home}, not #{homedir}!", :error raise WrongHomedir end else log "Creating #{user} user..." shell = [:shell] ? [:shell] : '/bin/bash' `useradd -d "#{homedir}" -s "#{shell}" -mr "#{user}"` end return true end |
#find_processes(regex) ⇒ Array<String>
Get a list of process matching a Regexp
65 66 67 |
# File 'lib/doable/helpers/linux.rb', line 65 def find_processes(regex) `ps aux`.chomp.split("\n").map {|l| l.split(nil, 11) }.collect {|p| p if p[10].match(regex)}.compact end |
#find_user(user, noisy = false) ⇒ Array
Die if a user doesn’t exist
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/doable/helpers/linux.rb', line 167 def find_user(user, noisy = false) # Create an Array of Arrays storing all known system users and their attributes all_users = `getent passwd`.chomp.split("\n").map {|line| line.split(':')} # Determine if the user we want exists this_user = all_users.collect {|u| u if u[0] == user}.compact if this_user.size > 1 log "Multiple instances of user #{user} found. This is known to cause problems.", :error raise DuplicateUsers elsif this_user.size < 1 log "Missing Critical User '#{user}'!", :error raise MissingUser else log "Found required user '#{user}' with uid #{this_user.flatten[2]}..." if noisy end return this_user.flatten end |
#have_executable?(name) ⇒ String, false
Does the system have an executable in $PATH? If not, return false.
79 80 81 82 83 84 85 86 |
# File 'lib/doable/helpers/linux.rb', line 79 def have_executable?(name) app_path = `which #{name}`.chomp if app_path.match(name) return app_path else return false end end |
#kill(pid, signal = "TERM") ⇒ Object
Kill a process
72 73 74 |
# File 'lib/doable/helpers/linux.rb', line 72 def kill(pid, signal = "TERM") Process.kill(signal, pid) end |
#run_as_user(user, command) ⇒ Object
Linux specific way to run something as another user. Command must be passed as a String.
248 249 250 251 |
# File 'lib/doable/helpers/linux.rb', line 248 def run_as_user(user, command) log "Running '#{command}' as '#{user}'..." tee("su -l #{user} -c \"#{command}\"") end |
#set_nofile(user, limit) ⇒ Boolean
Set the max number of open files for a user (nofiles) (sets both hard and soft, errors out if user is already listed in limits.conf) Currently does NOT verify the existence of the specified user on the system
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/doable/helpers/linux.rb', line 259 def set_nofile(user, limit) # See if the user is already in the limits.conf file user_entries = `grep -E '^#{user}(\s|\t)+' /etc/security/limits.conf`.chomp.split("\n") if user_entries.empty? # Doing this the lazy way for now... this is probably dangerous for very large files # Open and copy the current content of the limits file plus a few extra lines towards the end current_file = File.readlines("/etc/security/limits.conf") temporary = Tempfile.new("new_limits") current_file[0..(current_file.size - 2)].each {|l| temporary.write l } temporary.write "#{user}\t\tsoft\tnofile\t\t#{limit}\n" temporary.write "#{user}\t\thard\tnofile\t\t#{limit}\n" temporary.write "\n" temporary.write current_file[current_file.size - 1] temporary.rewind # Create a backup of the current file FileUtils.cp "/etc/security/limits.conf", "/etc/security/limits.conf.#{Time.now.to_i}" # Clear out the current file File.truncate("/etc/security/limits.conf", 0) # Copy the temporary (new) file to the existing current_file = File.new("/etc/security/limits.conf", "w") temporary.each {|l| current_file.puts l } # Close everything up temporary.close temporary.unlink current_file.close return true else log "User '#{user}' already has a specific entry in /etc/security/limits.conf. Ensure 'nofile' is at least #{limit}.", :warn return false end end |
#set_user_password(user, new_pass) ⇒ Boolean
This may only work on RHEL (and the like), as chpasswd may not be available on other OS’s
Sets a user’s password
154 155 156 157 158 159 |
# File 'lib/doable/helpers/linux.rb', line 154 def set_user_password(user, new_pass) log "Setting password for #{user}..." `echo "#{user}:#{new_pass}" | chpasswd` raise FailedPasswordChange unless $?.success? return $?.success? end |
#update_user_gid(user, gid) ⇒ Object
Set a user’s gid (default group)
209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/doable/helpers/linux.rb', line 209 def update_user_gid(user, gid) user_details = find_user(user) if user_details[3] != gid log "Setting default group for #{user} to #{gid}..." `usermod -g #{gid} "#{user}"` raise FailedUserModification unless $?.success? log "Fixing permissions..." `chown -R #{user}:#{gid} "#{user_details[5]}"` end return gid end |