Class: Makit::Process

Inherits:
Object
  • Object
show all
Defined in:
lib/makit/process.rb

Overview

Cross-platform process management utilities

This class provides methods for checking, listing, and terminating processes across different operating systems (Windows, Linux, macOS). It abstracts platform-specific commands into a unified interface.

Class Method Summary collapse

Class Method Details

.is_running?(name) ⇒ Boolean

Check if a process with the given name is currently running

Uses platform-specific commands:

  • Windows: tasklist command

  • Unix: ps command with grep filtering

Parameters:

  • name (String)

    Name of the process to check (without .exe extension)

Returns:

  • (Boolean)

    True if the process is running, false otherwise



19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/makit/process.rb', line 19

def self.is_running?(name)
  return false if name.nil? || name.strip.empty?

  # provide a cross-platform way to check if a process is running
  results = if Makit::Environment.is_windows?
      # on windows, use the tasklist command
      `tasklist /FI "imagename eq #{name}.exe" 2>nul`
    else
      # on linux/mac, use the ps command
      `ps aux | grep "#{name}" | grep -v grep 2>/dev/null`
    end
  results.include?(name)
end

.kill(name) ⇒ Array<String>

Terminate all processes that match a given name

Uses platform-specific termination commands:

  • Windows: taskkill command

  • Unix: kill command with SIGKILL (-9)

Parameters:

  • name (String)

    Name of the process(es) to terminate

Returns:

  • (Array<String>)

    Array of killed process IDs (empty if none found/killed)



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/makit/process.rb', line 41

def self.kill(name)
  return [] if name.nil? || name.strip.empty?

  killed_pids = []

  if Makit::Environment.is_windows?
    # Windows: Use tasklist to find PIDs first, then kill them
    begin
      # Find processes by name
      tasklist_output = `tasklist /FI "imagename eq #{name}.exe" /FO CSV 2>nul`

      # Parse CSV output to extract PIDs
      lines = tasklist_output.split("\n")
      if lines.length > 1 # Skip header line
        lines[1..].each do |line|
          parts = line.split(",")
          next unless parts.length >= 2

          pid = parts[1]&.gsub('"', "")&.strip
          next unless pid && !pid.empty? && pid.match?(/^\d+$/)

          begin
            `taskkill /PID #{pid} /F 2>nul`
            killed_pids << pid
          rescue StandardError => e
            # Log error but continue with other processes
            puts "Failed to kill process #{pid}: #{e.message}"
          end
        end
      end
    rescue StandardError => e
      # If tasklist fails, try direct taskkill by name
      begin
        `taskkill /IM "#{name}.exe" /F 2>nul`
        # Since we can't get PIDs from direct kill, return empty array
        # but don't raise error
      rescue StandardError => e2
        # Both methods failed, return empty array
        puts "Failed to kill processes by name #{name}: #{e2.message}"
      end
    end
  else
    # Unix (Linux/Mac): Use pgrep to find PIDs, then kill them
    begin
      # Use pgrep to find PIDs, handle both Linux and Mac
      pids = if Makit::Environment.is_mac?
          # Mac: pgrep -f might not work the same way
          `pgrep -x "#{name}" 2>/dev/null`.split("\n").reject(&:empty?)
        else
          # Linux: pgrep -f works well
          `pgrep -f "#{name}" 2>/dev/null`.split("\n").reject(&:empty?)
        end

      pids.each do |pid|
        next unless pid.match?(/^\d+$/)

        begin
          `kill -9 #{pid} 2>/dev/null`
          killed_pids << pid
        rescue StandardError => e
          puts "Failed to kill process #{pid}: #{e.message}"
        end
      end
    rescue StandardError => e
      # If pgrep fails, return empty array but don't raise error
      puts "Failed to find processes by name #{name}: #{e.message}"
    end
  end

  killed_pids
end

.listString

List all running processes on the system

Uses platform-specific commands to get a complete process listing:

  • Windows: tasklist command

  • Unix: ps aux command

Returns:

  • (String)

    Raw output from the system process listing command



120
121
122
123
124
125
126
# File 'lib/makit/process.rb', line 120

def self.list
  if Makit::Environment.is_windows?
    `tasklist 2>nul`
  else
    `ps aux 2>/dev/null`
  end
end

.list_current_userString

List all running processes for the current user

Filters the process list to show only processes owned by the current user. Uses platform-specific filtering:

  • Windows: tasklist with USERNAME filter

  • Unix: ps aux with grep filtering

Returns:

  • (String)

    Raw output from the filtered process listing command



136
137
138
139
140
141
142
# File 'lib/makit/process.rb', line 136

def self.list_current_user
  if Makit::Environment.is_windows?
    `tasklist /FI "STATUS eq running and USERNAME eq #{Makit::Environment.current_user}" 2>nul`
  else
    `ps aux | grep "#{Makit::Environment.current_user}" | grep -v grep 2>/dev/null`
  end
end

.list_current_user_processes(name) ⇒ Array<String>

List processes for the current user filtered by name

Returns an array of process lines for consistency across platforms. Filters by both current user and process name.

Parameters:

  • name (String)

    Process name to filter by

Returns:

  • (Array<String>)

    Array of process lines matching the criteria



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/makit/process.rb', line 151

def self.list_current_user_processes(name)
  if Makit::Environment.is_windows?
    # filter the results to only include the current user
    results = `tasklist /FI "STATUS eq running and USERNAME eq #{Makit::Environment.current_user}" 2>nul`
    results.split("\n").select { |line| line.include?(Makit::Environment.current_user) }
  else
    # Unix (Linux/Mac): return as array for consistency
    results = `ps aux | grep "#{name}" | grep -v grep 2>/dev/null`
    results.split("\n").reject(&:empty?)
  end
end