class Heroku::Command::Ps
manage dynos (dynos, workers)
Constants
- COSTS
Public Instance Methods
dynos()
click to toggle source
ps:dynos [QTY] DEPRECATED: use `heroku ps:scale dynos=N` scale to QTY web processes if QTY is not specified, display the number of web processes currently running
Example:
$ heroku ps:dynos 3 Scaling dynos... done, now running 3
# File lib/heroku/command/ps.rb, line 21 def dynos # deprecation notice added to v2.21.3 on 03/16/12 display("~ `heroku ps:dynos QTY` has been deprecated and replaced with `heroku ps:scale dynos=QTY`") dynos = shift_argument validate_arguments! if dynos action("Scaling dynos") do new_dynos = api.put_dynos(app, dynos).body["dynos"] status("now running #{new_dynos}") end else app_data = api.get_app(app).body if app_data["stack"] == "cedar" raise(Heroku::Command::CommandFailed, "For Cedar apps, use `heroku ps`") else display("#{app} is running #{quantify("dyno", app_data["dynos"])}") end end end
index()
click to toggle source
ps list dynos for an app
Example:
$ heroku ps === run: one-off dyno run.1: up for 5m: `bash` === web: `bundle exec thin start -p $PORT` web.1: created for 30s
# File lib/heroku/command/ps.rb, line 95 def index validate_arguments! quota_resp = api.request( :expects => [200, 404], :method => :post, :path => "/apps/#{app}/actions/get-quota", :headers => { "Accept" => "application/vnd.heroku+json; version=3.app-quotas", "Content-Type" => "application/json" } ) if quota_resp.status = 200 quota = quota_resp.body now = Time.now.getutc quota_message = if quota["allow_until"] "Free quota left:" elsif quota["deny_until"] "Free quota exhausted. Unidle available in:" end if quota_message quota_timestamp = (quota["allow_until"] ? Time.parse(quota["allow_until"]).getutc : Time.parse(quota["deny_until"]).getutc) time_left = time_remaining(Time.now.getutc, quota_timestamp) display("#{quota_message} #{time_left}") end end processes_resp = api.request( :expects => 200, :method => :get, :path => "/apps/#{app}/dynos", :headers => { "Accept" => "application/vnd.heroku+json; version=3", "Content-Type" => "application/json" } ) processes = processes_resp.body processes_by_command = Hash.new {|hash,key| hash[key] = []} processes.each do |process| now = Time.now type = process["type"] elapsed = now - Time.iso8601(process['updated_at']) since = time_ago(now - elapsed) size = process["size"] || "1X" if type == "run" key = "run: one-off processes" item = "%s (%s): %s %s: `%s`" % [ process["name"], size, process["state"], since, process["command"] ] else key = "#{type} (#{size}): `#{process["command"]}`" item = "%s: %s %s" % [ process['name'], process['state'], since ] end processes_by_command[key] << item end extract_run_id = /\.(\d+).*:/ processes_by_command.keys.each do |key| processes_by_command[key] = processes_by_command[key].sort do |x,y| x.match(extract_run_id).captures.first.to_i <=> y.match(extract_run_id).captures.first.to_i end end processes_by_command.keys.sort.each do |key| styled_header(key) styled_array(processes_by_command[key], :sort => false) end end
restart()
click to toggle source
ps:restart [DYNO] restart an app dyno if DYNO is not specified, restarts all dynos on the app
Examples:
$ heroku ps:restart web.1 Restarting web.1 dyno... done $ heroku ps:restart web Restarting web dyno... done $ heroku ps:restart Restarting dynos... done
# File lib/heroku/command/ps.rb, line 182 def restart dyno = shift_argument validate_arguments! message, options = case dyno when NilClass ["Restarting dynos", {}] when /.+\..+/ ps = args.first ["Restarting #{ps} dyno", { :ps => ps }] else type = args.first ["Restarting #{type} dynos", { :type => type }] end action(message) do api.post_ps_restart(app, options) end end
scale()
click to toggle source
ps:scale DYNO1=AMOUNT1 [DYNO2=AMOUNT2 ...] scale dynos by the given amount appending a size (eg. web=2:2X) allows simultaneous scaling and resizing
Examples:
$ heroku ps:scale web=3:2X worker+1 Scaling dynos... done, now running web at 3:2X, worker at 1:1X.
# File lib/heroku/command/ps.rb, line 215 def scale requires_preauth changes = args.map do |arg| if change = arg.scan(/^([a-zA-Z0-9_]+)([=+-]\d+)(?::([\w-]+))?$/).first formation, quantity, size = change quantity = quantity[1..-1].to_i if quantity[0] == "=" { "type" => formation, "quantity" => quantity, "size" => size} end end.compact if changes.empty? error("Usage: heroku ps:scale DYNO1=AMOUNT1[:SIZE] [DYNO2=AMOUNT2 ...]\nMust specify DYNO and AMOUNT to scale.\nDYNO must be alphanumeric.") end action("Scaling dynos") do new_scales = scale_dynos(get_formation, changes) .map {|p| "#{p["type"]} at #{p["quantity"]}:#{p["size"]}" } status("now running " + new_scales.join(", ") + ".") end end
stop()
click to toggle source
ps:stop DYNOS
stop an app dyno
Examples:
$ heroku stop run.3 Stopping run.3 dyno… done
$ heroku stop run Stopping run dynos… done
# File lib/heroku/command/ps.rb, line 251 def stop dyno = shift_argument validate_arguments! message, options = case dyno when NilClass error("Usage: heroku ps:stop DYNO\nMust specify DYNO to stop.") when /.+\..+/ ps = args.first ["Stopping #{ps} dyno", { :ps => ps }] else type = args.first ["Stopping #{type} dynos", { :type => type }] end action(message) do api.post_ps_stop(app, options) end end
type()
click to toggle source
ps:type [TYPE | DYNO=TYPE [DYNO=TYPE …]]
manage dyno types
called with no arguments shows the current dyno type
called with one argument sets the type where type is one of free|hobby|standard-1x|standard-2x|performance
called with 1..n DYNO=TYPE arguments sets the type per dyno
# File lib/heroku/command/ps.rb, line 284 def type requires_preauth app formation = get_formation changes = if args.any?{|arg| arg =~ /=/} args.map do |arg| if arg =~ /^([a-zA-Z0-9_]+)=([\w-]+)$/ p = formation.find{|f| f["type"] == $1}.clone p["size"] = $2 p end end.compact elsif args.any? size = shift_argument.downcase validate_arguments! formation.map{|p| p["size"] = size; p} end scale_dynos(formation, changes) if changes display_dyno_type_and_costs(get_formation) end
Also aliased as: resize
workers()
click to toggle source
ps:workers [QTY] DEPRECATED: use `heroku ps:scale workers=N` scale to QTY background processes if QTY is not specified, display the number of background processes currently running
Example:
$ heroku ps:dynos 3 Scaling workers... done, now running 3
# File lib/heroku/command/ps.rb, line 58 def workers # deprecation notice added to v2.21.3 on 03/16/12 display("~ `heroku ps:workers QTY` has been deprecated and replaced with `heroku ps:scale workers=QTY`") workers = shift_argument validate_arguments! if workers action("Scaling workers") do new_workers = api.put_workers(app, workers).body["workers"] status("now running #{new_workers}") end else app_data = api.get_app(app).body if app_data["stack"] == "cedar" raise(Heroku::Command::CommandFailed, "For Cedar apps, use `heroku ps`") else display("#{app} is running #{quantify("worker", app_data["workers"])}") end end end
Private Instance Methods
display_dyno_type_and_costs(formation)
click to toggle source
# File lib/heroku/command/ps.rb, line 322 def display_dyno_type_and_costs(formation) annotated = formation.sort_by{|d| d['type']}.map do |dyno| cost = COSTS[dyno["size"]] { 'dyno' => dyno['type'], 'type' => dyno['size'].rjust(4), 'qty' => dyno['quantity'].to_s.rjust(3), 'cost/mo' => cost ? (cost * dyno["quantity"]).to_s.rjust(7) : '' } end if annotated.empty? error "No process types on #{app}.\nUpload a Procfile to add process types.\nhttps://devcenter.heroku.com/articles/procfile" else display_table(annotated, annotated.first.keys, annotated.first.keys) end end
get_formation()
click to toggle source
# File lib/heroku/command/ps.rb, line 340 def get_formation api.request( :expects => 200, :method => :get, :path => "/apps/#{app}/formation", :headers => { "Accept" => "application/vnd.heroku+json; version=3", "Content-Type" => "application/json" } ).body end
patch_tier(process_tier)
click to toggle source
# File lib/heroku/command/ps.rb, line 310 def patch_tier(process_tier) api.request( :method => :patch, :path => "/apps/#{app}", :body => json_encode("process_tier" => process_tier), :headers => { "Accept" => "application/vnd.heroku+json; version=edge", "Content-Type" => "application/json" } ) end
scale_dynos(formation, changes)
click to toggle source
# File lib/heroku/command/ps.rb, line 352 def scale_dynos(formation, changes) # The V3 API supports atomic scale+resize, so we make a raw request here # since the heroku-api gem still only supports V2. resp = api.request( :expects => 200, :method => :patch, :path => "/apps/#{app}/formation", :body => json_encode("updates" => changes), :headers => { "Accept" => "application/vnd.heroku+json; version=3", "Content-Type" => "application/json" } ) resp.body.select {|p| changes.any?{|c| c["type"] == p["type"]} } end