chef 0.10.10.beta.1 → 0.10.10.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/README.rdoc +1 -1
  2. data/distro/common/html/chef-client.8.html +3 -3
  3. data/distro/common/html/chef-expander.8.html +3 -3
  4. data/distro/common/html/chef-expanderctl.8.html +3 -3
  5. data/distro/common/html/chef-server-webui.8.html +3 -3
  6. data/distro/common/html/chef-server.8.html +3 -3
  7. data/distro/common/html/chef-solo.8.html +3 -3
  8. data/distro/common/html/chef-solr.8.html +3 -3
  9. data/distro/common/html/knife-bootstrap.1.html +3 -3
  10. data/distro/common/html/knife-client.1.html +3 -3
  11. data/distro/common/html/knife-configure.1.html +3 -3
  12. data/distro/common/html/knife-cookbook-site.1.html +3 -3
  13. data/distro/common/html/knife-cookbook.1.html +3 -3
  14. data/distro/common/html/knife-data-bag.1.html +7 -3
  15. data/distro/common/html/knife-environment.1.html +3 -3
  16. data/distro/common/html/knife-exec.1.html +3 -3
  17. data/distro/common/html/knife-index.1.html +3 -3
  18. data/distro/common/html/knife-node.1.html +3 -3
  19. data/distro/common/html/knife-role.1.html +3 -3
  20. data/distro/common/html/knife-search.1.html +3 -3
  21. data/distro/common/html/knife-ssh.1.html +3 -3
  22. data/distro/common/html/knife-status.1.html +3 -3
  23. data/distro/common/html/knife-tag.1.html +3 -3
  24. data/distro/common/html/knife.1.html +3 -3
  25. data/distro/common/html/shef.1.html +3 -3
  26. data/distro/common/man/man1/knife-bootstrap.1 +1 -1
  27. data/distro/common/man/man1/knife-client.1 +1 -1
  28. data/distro/common/man/man1/knife-configure.1 +1 -1
  29. data/distro/common/man/man1/knife-cookbook-site.1 +1 -1
  30. data/distro/common/man/man1/knife-cookbook.1 +1 -1
  31. data/distro/common/man/man1/knife-data-bag.1 +7 -1
  32. data/distro/common/man/man1/knife-environment.1 +1 -1
  33. data/distro/common/man/man1/knife-exec.1 +1 -1
  34. data/distro/common/man/man1/knife-index.1 +1 -1
  35. data/distro/common/man/man1/knife-node.1 +1 -1
  36. data/distro/common/man/man1/knife-role.1 +1 -1
  37. data/distro/common/man/man1/knife-search.1 +1 -1
  38. data/distro/common/man/man1/knife-ssh.1 +1 -1
  39. data/distro/common/man/man1/knife-status.1 +1 -1
  40. data/distro/common/man/man1/knife-tag.1 +1 -1
  41. data/distro/common/man/man1/knife.1 +1 -1
  42. data/distro/common/man/man1/shef.1 +1 -1
  43. data/distro/common/man/man8/chef-client.8 +1 -1
  44. data/distro/common/man/man8/chef-expander.8 +1 -1
  45. data/distro/common/man/man8/chef-expanderctl.8 +1 -1
  46. data/distro/common/man/man8/chef-server-webui.8 +1 -1
  47. data/distro/common/man/man8/chef-server.8 +1 -1
  48. data/distro/common/man/man8/chef-solo.8 +1 -1
  49. data/distro/common/man/man8/chef-solr.8 +1 -1
  50. data/distro/common/markdown/man1/knife-data-bag.mkd +4 -0
  51. data/lib/chef/application/client.rb +15 -1
  52. data/lib/chef/application/solo.rb +15 -1
  53. data/lib/chef/application/windows_service.rb +15 -1
  54. data/lib/chef/certificate.rb +18 -51
  55. data/lib/chef/client.rb +31 -1
  56. data/lib/chef/json_compat.rb +1 -1
  57. data/lib/chef/knife.rb +23 -6
  58. data/lib/chef/knife/bootstrap.rb +7 -0
  59. data/lib/chef/knife/bootstrap/archlinux-gems.erb +1 -1
  60. data/lib/chef/knife/bootstrap/centos5-gems.erb +1 -1
  61. data/lib/chef/knife/bootstrap/chef-full.erb +1 -1
  62. data/lib/chef/knife/bootstrap/fedora13-gems.erb +1 -1
  63. data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +1 -1
  64. data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +1 -1
  65. data/lib/chef/knife/core/bootstrap_context.rb +4 -0
  66. data/lib/chef/knife/core/generic_presenter.rb +1 -1
  67. data/lib/chef/knife/core/object_loader.rb +39 -2
  68. data/lib/chef/knife/data_bag_from_file.rb +68 -19
  69. data/lib/chef/knife/ssh.rb +2 -1
  70. data/lib/chef/platform.rb +8 -0
  71. data/lib/chef/provider/cron.rb +70 -56
  72. data/lib/chef/provider/cron/solaris.rb +16 -143
  73. data/lib/chef/provider/deploy.rb +1 -1
  74. data/lib/chef/provider/group/groupadd.rb +1 -4
  75. data/lib/chef/provider/mdadm.rb +1 -1
  76. data/lib/chef/provider/mount/mount.rb +14 -2
  77. data/lib/chef/provider/package.rb +7 -1
  78. data/lib/chef/provider/package/freebsd.rb +30 -6
  79. data/lib/chef/provider/package/pacman.rb +1 -0
  80. data/lib/chef/provider/package/rubygems.rb +2 -4
  81. data/lib/chef/provider/remote_directory.rb +1 -1
  82. data/lib/chef/provider/service/freebsd.rb +32 -46
  83. data/lib/chef/provider/service/init.rb +8 -5
  84. data/lib/chef/provider/service/simple.rb +57 -48
  85. data/lib/chef/provider/service/upstart.rb +13 -5
  86. data/lib/chef/provider/user/useradd.rb +6 -1
  87. data/lib/chef/resource/mdadm.rb +9 -0
  88. data/lib/chef/resource/service.rb +9 -1
  89. data/lib/chef/rest.rb +9 -9
  90. data/lib/chef/version.rb +1 -1
  91. metadata +177 -28
@@ -172,8 +172,13 @@ class Chef
172
172
  end
173
173
  end
174
174
 
175
+ def network_device?
176
+ @new_resource.device =~ /:/ || @new_resource.device =~ /\/\//
177
+ end
178
+
175
179
  def device_should_exist?
176
- @new_resource.device !~ /:/ && @new_resource.device !~ /\/\// && @new_resource.fstype != "tmpfs" && @new_resource.fstype != 'fuse'
180
+ ( not network_device? ) &&
181
+ ( not %w[ tmpfs fuse ].include? @new_resource.fstype )
177
182
  end
178
183
 
179
184
  private
@@ -216,7 +221,14 @@ class Chef
216
221
  end
217
222
 
218
223
  def device_mount_regex
219
- ::File.symlink?(device_real) ? "(?:#{Regexp.escape(device_real)})|(?:#{Regexp.escape(::File.readlink(device_real))})" : Regexp.escape(device_real)
224
+ if network_device?
225
+ # ignore trailing slash
226
+ Regexp.escape(device_real)+"/?"
227
+ elsif ::File.symlink?(device_real)
228
+ "(?:#{Regexp.escape(device_real)})|(?:#{Regexp.escape(::File.readlink(device_real))})"
229
+ else
230
+ Regexp.escape(device_real)
231
+ end
220
232
  end
221
233
 
222
234
  def device_fstab_regex
@@ -36,7 +36,7 @@ class Chef
36
36
 
37
37
  def action_install
38
38
  # If we specified a version, and it's not the current version, move to the specified version
39
- if @new_resource.version != nil && @new_resource.version != @current_resource.version
39
+ if @new_resource.version != nil && !target_version_already_installed?
40
40
  install_version = @new_resource.version
41
41
  # If it's not installed at all, install it
42
42
  elsif @current_resource.version == nil
@@ -199,6 +199,12 @@ class Chef
199
199
  options ? " #{options}" : ""
200
200
  end
201
201
 
202
+ private
203
+
204
+ def target_version_already_installed?
205
+ @new_resource.version == @current_resource.version
206
+ end
207
+
202
208
  end
203
209
  end
204
210
  end
@@ -68,13 +68,29 @@ class Chef
68
68
  ports_makefile_variable_value("PORTVERSION")
69
69
  end
70
70
 
71
+ def file_candidate_version_path
72
+ Dir["#{@new_resource.source}/#{@current_resource.package_name}*"][-1].to_s
73
+ end
74
+
75
+ def file_candidate_version
76
+ file_candidate_version_path.split(/-/).last.split(/.tbz/).first
77
+ end
78
+
71
79
  def load_current_resource
72
80
  @current_resource.package_name(@new_resource.package_name)
73
81
 
74
82
  @current_resource.version(current_installed_version)
75
83
  Chef::Log.debug("#{@new_resource} current version is #{@current_resource.version}") if @current_resource.version
76
84
 
77
- @candidate_version = ports_candidate_version
85
+ case @new_resource.source
86
+ when /^http/, /^ftp/
87
+ @candidate_version = "0.0.0"
88
+ when /^\//
89
+ @candidate_version = file_candidate_version
90
+ else
91
+ @candidate_version = ports_candidate_version
92
+ end
93
+
78
94
  Chef::Log.debug("#{@new_resource} ports candidate version is #{@candidate_version}") if @candidate_version
79
95
 
80
96
  @current_resource
@@ -86,10 +102,14 @@ class Chef
86
102
 
87
103
  # The name of the package (without the version number) as understood by pkg_add and pkg_info
88
104
  def package_name
89
- if ports_makefile_variable_value("PKGNAME") =~ /^(.+)-[^-]+$/
90
- $1
105
+ if ::File.exist?("/usr/ports/Makefile")
106
+ if ports_makefile_variable_value("PKGNAME") =~ /^(.+)-[^-]+$/
107
+ $1
108
+ else
109
+ raise Chef::Exceptions::Package, "Unexpected form for PKGNAME variable in #{port_path}/Makefile"
110
+ end
91
111
  else
92
- raise Chef::Exceptions::Package, "Unexpected form for PKGNAME variable in #{port_path}/Makefile"
112
+ @new_resource.package_name
93
113
  end
94
114
  end
95
115
 
@@ -99,10 +119,14 @@ class Chef
99
119
  when /^ports$/
100
120
  shell_out!("make -DBATCH install", :timeout => 1200, :env => nil, :cwd => port_path).status
101
121
  when /^http/, /^ftp/
102
- shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGESITE" => @new_resource.source, 'LC_ALL' => nil }).status
122
+ if @new_resource.source =~ /\/$/
123
+ shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGESITE" => @new_resource.source, 'LC_ALL' => nil }).status
124
+ else
125
+ shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGEROOT" => @new_resource.source, 'LC_ALL' => nil }).status
126
+ end
103
127
  Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
104
128
  when /^\//
105
- shell_out!("pkg_add #{@new_resource.name}", :env => { "PKG_PATH" => @new_resource.source , 'LC_ALL'=>nil}).status
129
+ shell_out!("pkg_add #{file_candidate_version_path}", :env => { "PKG_PATH" => @new_resource.source , 'LC_ALL'=>nil}).status
106
130
  Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
107
131
  else
108
132
  shell_out!("pkg_add -r #{latest_link_name}", :env => nil).status
@@ -34,6 +34,7 @@ class Chef
34
34
  Chef::Log.debug("#{@new_resource} checking pacman for #{@new_resource.package_name}")
35
35
  status = popen4("pacman -Qi #{@new_resource.package_name}") do |pid, stdin, stdout, stderr|
36
36
  stdout.each do |line|
37
+ line.force_encoding(Encoding::UTF_8) if line.respond_to?(:force_encoding)
37
38
  case line
38
39
  when /^Version(\s?)*: (.+)$/
39
40
  Chef::Log.debug("#{@new_resource} current version is #{$2}")
@@ -353,7 +353,7 @@ class Chef
353
353
  end
354
354
 
355
355
  def is_omnibus?
356
- if RbConfig::CONFIG['bindir'] == "/opt/opscode/embedded/bin"
356
+ if RbConfig::CONFIG['bindir'] == "/opt/chef/embedded/bin"
357
357
  Chef::Log.debug("#{@new_resource} detected omnibus installation in #{RbConfig::CONFIG['bindir']}")
358
358
  # Omnibus installs to a static path because of linking on unix, find it.
359
359
  true
@@ -444,9 +444,7 @@ class Chef
444
444
  def target_version_already_installed?
445
445
  return false unless @current_resource && @current_resource.version
446
446
  return false if @current_resource.version.nil?
447
- # in the future we could support squiggly requirements like "~> 1.2.0"
448
- # for now, the behavior when using anything other than exact
449
- # requirements is undefined.
447
+
450
448
  Gem::Requirement.new(@new_resource.version).satisfied_by?(Gem::Version.new(@current_resource.version))
451
449
  end
452
450
 
@@ -62,7 +62,7 @@ class Chef
62
62
  def purge_unmanaged_files(unmanaged_files)
63
63
  if @new_resource.purge
64
64
  unmanaged_files.sort.reverse.each do |f|
65
- if ::File.directory?(f)
65
+ if ::File.directory?(f) && !::File.symlink?(f)
66
66
  Dir::rmdir(f)
67
67
  Chef::Log.debug("#{@new_resource} removed directory #{f}")
68
68
  else
@@ -16,6 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ require 'chef/mixin/shell_out'
19
20
  require 'chef/provider/service'
20
21
  require 'chef/mixin/command'
21
22
 
@@ -24,6 +25,8 @@ class Chef
24
25
  class Service
25
26
  class Freebsd < Chef::Provider::Service::Init
26
27
 
28
+ include Chef::Mixin::ShellOut
29
+
27
30
  def load_current_resource
28
31
  @current_resource = Chef::Resource::Service.new(@new_resource.name)
29
32
  @current_resource.service_name(@new_resource.service_name)
@@ -38,52 +41,7 @@ class Chef
38
41
  end
39
42
  Chef::Log.debug("#{@current_resource} found at #{@init_command}")
40
43
 
41
- if @new_resource.supports[:status]
42
- begin
43
- if run_command(:command => "#{@init_command} status") == 0
44
- @current_resource.running true
45
- Chef::Log.debug("#{@new_resource} is running")
46
- end
47
- rescue Chef::Exceptions::Exec
48
- @current_resource.running false
49
- nil
50
- end
51
-
52
- elsif @new_resource.status_command
53
- begin
54
- if run_command(:command => @new_resource.status_command) == 0
55
- @current_resource.running true
56
- Chef::Log.debug("#{@new_resource} is running")
57
- end
58
- rescue Chef::Exceptions::Exec
59
- @current_resource.running false
60
- nil
61
- end
62
-
63
- else
64
- Chef::Log.debug("#{@new_resource} does not support status and you have not specified a status command, falling back to process table inspection")
65
-
66
- if node[:command][:ps].nil? or node[:command][:ps].empty?
67
- raise Chef::Exceptions::Service, "#{@new_resource} could not determine how to inspect the process table, please set this nodes 'ps' attribute"
68
- end
69
-
70
- status = popen4(node[:command][:ps]) do |pid, stdin, stdout, stderr|
71
- r = Regexp.new(@new_resource.pattern)
72
- Chef::Log.debug("#{@new_resource} attempting to match #{@new_resource.pattern} (#{r}) against process table")
73
- stdout.each_line do |line|
74
- if r.match(line)
75
- @current_resource.running true
76
- break
77
- end
78
- end
79
- @current_resource.running false unless @current_resource.running
80
- end
81
- unless status.exitstatus == 0
82
- raise Chef::Exceptions::Service, "Command #{node[:command][:ps]} failed"
83
- else
84
- Chef::Log.debug("#{@new_resource} #{node[:command][:ps]} exited and parsed successfully, process running: #{@current_resource.running}")
85
- end
86
- end
44
+ determine_current_status!
87
45
 
88
46
  if ::File.exists?("/etc/rc.conf")
89
47
  read_rc_conf.each do |line|
@@ -104,6 +62,34 @@ class Chef
104
62
  @current_resource
105
63
  end
106
64
 
65
+ def start_service
66
+ if @new_resource.start_command
67
+ super
68
+ else
69
+ shell_out!("#{@init_command} faststart")
70
+ end
71
+ end
72
+
73
+ def stop_service
74
+ if @new_resource.stop_command
75
+ super
76
+ else
77
+ shell_out!("#{@init_command} faststop")
78
+ end
79
+ end
80
+
81
+ def restart_service
82
+ if @new_resource.restart_command
83
+ super
84
+ elsif @new_resource.supports[:restart]
85
+ shell_out!("#{@init_command} fastrestart")
86
+ else
87
+ stop_service
88
+ sleep 1
89
+ start_service
90
+ end
91
+ end
92
+
107
93
  def read_rc_conf
108
94
  ::File.open("/etc/rc.conf", 'r') { |file| file.readlines }
109
95
  end
@@ -16,6 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ require 'chef/mixin/shell_out'
19
20
  require 'chef/provider/service'
20
21
  require 'chef/provider/service/simple'
21
22
  require 'chef/mixin/command'
@@ -24,7 +25,9 @@ class Chef
24
25
  class Provider
25
26
  class Service
26
27
  class Init < Chef::Provider::Service::Simple
27
-
28
+
29
+ include Chef::Mixin::ShellOut
30
+
28
31
  def initialize(new_resource, run_context)
29
32
  super
30
33
  @init_command = "/etc/init.d/#{@new_resource.service_name}"
@@ -34,7 +37,7 @@ class Chef
34
37
  if @new_resource.start_command
35
38
  super
36
39
  else
37
- run_command(:command => "#{@init_command} start")
40
+ shell_out!("#{@init_command} start")
38
41
  end
39
42
  end
40
43
 
@@ -42,7 +45,7 @@ class Chef
42
45
  if @new_resource.stop_command
43
46
  super
44
47
  else
45
- run_command(:command => "#{@init_command} stop")
48
+ shell_out!("#{@init_command} stop")
46
49
  end
47
50
  end
48
51
 
@@ -50,7 +53,7 @@ class Chef
50
53
  if @new_resource.restart_command
51
54
  super
52
55
  elsif @new_resource.supports[:restart]
53
- run_command(:command => "#{@init_command} restart")
56
+ shell_out!("#{@init_command} restart")
54
57
  else
55
58
  stop_service
56
59
  sleep 1
@@ -62,7 +65,7 @@ class Chef
62
65
  if @new_resource.reload_command
63
66
  super
64
67
  elsif @new_resource.supports[:reload]
65
- run_command(:command => "#{@init_command} reload")
68
+ shell_out!("#{@init_command} reload")
66
69
  end
67
70
  end
68
71
  end
@@ -16,6 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ require 'chef/mixin/shell_out'
19
20
  require 'chef/provider/service'
20
21
  require 'chef/mixin/command'
21
22
 
@@ -23,18 +24,63 @@ class Chef
23
24
  class Provider
24
25
  class Service
25
26
  class Simple < Chef::Provider::Service
27
+
28
+ include Chef::Mixin::ShellOut
29
+
26
30
  def load_current_resource
27
31
  @current_resource = Chef::Resource::Service.new(@new_resource.name)
28
32
  @current_resource.service_name(@new_resource.service_name)
33
+
34
+ determine_current_status!
35
+
36
+ @current_resource
37
+ end
38
+
39
+ def start_service
40
+ if @new_resource.start_command
41
+ shell_out!(@new_resource.start_command)
42
+ else
43
+ raise Chef::Exceptions::Service, "#{self.to_s} requires that start_command to be set"
44
+ end
45
+ end
46
+
47
+ def stop_service
48
+ if @new_resource.stop_command
49
+ shell_out!(@new_resource.stop_command)
50
+ else
51
+ raise Chef::Exceptions::Service, "#{self.to_s} requires that stop_command to be set"
52
+ end
53
+ end
54
+
55
+ def restart_service
56
+ if @new_resource.restart_command
57
+ shell_out!(@new_resource.restart_command)
58
+ else
59
+ stop_service
60
+ sleep 1
61
+ start_service
62
+ end
63
+ end
64
+
65
+ def reload_service
66
+ if @new_resource.reload_command
67
+ shell_out!(@new_resource.reload_command)
68
+ else
69
+ raise Chef::Exceptions::Service, "#{self.to_s} requires that reload_command to be set"
70
+ end
71
+ end
72
+
73
+ protected
74
+ def determine_current_status!
29
75
  if @new_resource.status_command
30
76
  Chef::Log.debug("#{@new_resource} you have specified a status command, running..")
31
77
 
32
78
  begin
33
- if run_command(:command => @new_resource.status_command) == 0
79
+ if shell_out(@new_resource.status_command).exitstatus == 0
34
80
  @current_resource.running true
35
81
  Chef::Log.debug("#{@new_resource} is running")
36
82
  end
37
- rescue Chef::Exceptions::Exec
83
+ rescue Mixlib::ShellOut::ShellCommandFailed
38
84
  @current_resource.running false
39
85
  nil
40
86
  end
@@ -43,11 +89,11 @@ class Chef
43
89
  Chef::Log.debug("#{@new_resource} supports status, running")
44
90
 
45
91
  begin
46
- if run_command(:command => "#{@init_command} status") == 0
92
+ if shell_out("#{@init_command} status").exitstatus == 0
47
93
  @current_resource.running true
48
94
  Chef::Log.debug("#{@new_resource} is running")
49
95
  end
50
- rescue Chef::Exceptions::Exec
96
+ rescue Mixlib::ShellOut::ShellCommandFailed
51
97
  @current_resource.running false
52
98
  nil
53
99
  end
@@ -56,59 +102,22 @@ class Chef
56
102
  if ps_cmd.nil? or ps_cmd.empty?
57
103
  raise Chef::Exceptions::Service, "#{@new_resource} could not determine how to inspect the process table, please set this nodes 'command.ps' attribute"
58
104
  end
59
- status = popen4(ps_cmd) do |pid, stdin, stdout, stderr|
60
- r = Regexp.new(@new_resource.pattern)
61
- Chef::Log.debug "#{@new_resource} attempting to match '#{@new_resource.pattern}' (#{r.inspect}) against process list"
62
- stdout.each_line do |line|
105
+
106
+ r = Regexp.new(@new_resource.pattern)
107
+ Chef::Log.debug "#{@new_resource} attempting to match '#{@new_resource.pattern}' (#{r.inspect}) against process list"
108
+ begin
109
+ shell_out!(ps_cmd).stdout.each_line do |line|
63
110
  if r.match(line)
64
111
  @current_resource.running true
65
112
  break
66
113
  end
67
114
  end
68
115
  @current_resource.running false unless @current_resource.running
69
- end
70
- unless status.exitstatus == 0
71
- raise Chef::Exceptions::Service, "Command #{ps_cmd} failed"
72
- else
73
116
  Chef::Log.debug "#{@new_resource} running: #{@current_resource.running}"
117
+ rescue Mixlib::ShellOut::ShellCommandFailed
118
+ raise Chef::Exceptions::Service, "Command #{ps_cmd} failed"
74
119
  end
75
120
  end
76
-
77
- @current_resource
78
- end
79
-
80
- def start_service
81
- if @new_resource.start_command
82
- run_command(:command => @new_resource.start_command)
83
- else
84
- raise Chef::Exceptions::Service, "#{self.to_s} requires that start_command to be set"
85
- end
86
- end
87
-
88
- def stop_service
89
- if @new_resource.stop_command
90
- run_command(:command => @new_resource.stop_command)
91
- else
92
- raise Chef::Exceptions::Service, "#{self.to_s} requires that stop_command to be set"
93
- end
94
- end
95
-
96
- def restart_service
97
- if @new_resource.restart_command
98
- run_command(:command => @new_resource.restart_command)
99
- else
100
- stop_service
101
- sleep 1
102
- start_service
103
- end
104
- end
105
-
106
- def reload_service
107
- if @new_resource.reload_command
108
- run_command(:command => @new_resource.reload_command)
109
- else
110
- raise Chef::Exceptions::Service, "#{self.to_s} requires that reload_command to be set"
111
- end
112
121
  end
113
122
 
114
123
  def ps_cmd