or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-grunt-exec

Grunt plugin for executing shell commands with comprehensive configuration options

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/grunt-exec@3.0.x

To install, run

npx @tessl/cli install tessl/npm-grunt-exec@3.0.0

index.mddocs/

grunt-exec

grunt-exec is a Grunt plugin that provides comprehensive shell command execution capabilities within Grunt build processes. It offers extensive configuration options for process control, input/output handling, error management, and both synchronous and asynchronous execution modes with cross-platform compatibility.

Package Information

  • Package Name: grunt-exec
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install grunt-exec --save-dev

Core Imports

After installing, load the plugin in your Gruntfile:

grunt.loadNpmTasks('grunt-exec');

Basic Usage

grunt.initConfig({
  exec: {
    simple_command: 'echo "Hello World"',
    
    advanced_command: {
      command: 'ls -la',
      stdout: true,
      stderr: true,
      cwd: './src'
    },
    
    function_command: {
      cmd: function(arg1, arg2) {
        return 'echo "Arguments: ' + arg1 + ', ' + arg2 + '"';
      }
    }
  }
});

// Run tasks
grunt.registerTask('default', ['exec:simple_command']);

Architecture

grunt-exec is built around the Grunt multitask system:

  • Task Registration: The plugin registers an 'exec' multitask with Grunt
  • Configuration Processing: Each target configuration is processed to handle commands, options, and I/O settings
  • Process Execution: Uses Node.js child_process.spawn/spawnSync for reliable command execution
  • Output Management: Provides sophisticated stdout/stderr handling with buffering and piping options
  • Error Handling: Comprehensive error checking with customizable exit code validation

Capabilities

Shell Command Execution

Core capability for executing shell commands with comprehensive configuration options.

/**
 * Main plugin registration function
 * @param grunt - The Grunt object instance
 */
function(grunt: GruntObject): void;

/**
 * Exec task configuration object
 */
interface ExecTaskConfig {
  /** The shell command to execute (required) */
  command?: string | CommandFunction;
  /** Alias for command */
  cmd?: string | CommandFunction;
  /** Current working directory */
  cwd?: string | CwdFunction;
  /** Control stdin behavior */
  stdin?: boolean | string;
  /** Control stdout behavior */
  stdout?: boolean | string;
  /** Control stderr behavior */
  stderr?: boolean | string;
  /** Shorthand for stdio configuration */
  stdio?: 'inherit' | 'pipe' | 'ignore';
  /** Use synchronous execution */
  sync?: boolean;
  /** Expected exit code(s) */
  exitCode?: number | number[];
  /** Alias for exitCode */
  exitCodes?: number | number[];
  /** Custom callback function */
  callback?: CallbackFunction;
  /** Additional callback arguments */
  callbackArgs?: any[];
  /** Character encoding for output */
  encoding?: string;
  /** Maximum buffer size for output */
  maxBuffer?: number;
  /** Command timeout in milliseconds */
  timeout?: number;
  /** Signal to use when killing process */
  killSignal?: string;
  /** Shell to use for command execution */
  shell?: boolean | string;
  /** Advanced process options */
  options?: ProcessOptions;
}

/**
 * Command function type for dynamic commands
 */
interface CommandFunction {
  (...args: any[]): string;
}

/**
 * Working directory function type
 */
interface CwdFunction {
  (...args: any[]): string;
}

/**
 * Callback function for handling command results
 */
interface CallbackFunction {
  (error: Error | null, stdout: string | Buffer, stderr: string | Buffer, callbackArgs?: any[]): void;
}

/**
 * Advanced process options
 */
interface ProcessOptions {
  /** Current working directory */
  cwd?: string;
  /** Environment variables */
  env?: { [key: string]: string };
  /** Character encoding */
  encoding?: string;
  /** Shell to execute command with */
  shell?: string | boolean;
  /** Timeout in milliseconds */
  timeout?: number;
  /** Maximum buffer size */
  maxBuffer?: number;
  /** Kill signal */
  killSignal?: string;
  /** User identity */
  uid?: number;
  /** Group identity */
  gid?: number;
  /** Stdio configuration */
  stdio?: (string | number)[];
}

Task Configuration Patterns

grunt-exec supports multiple configuration patterns for different use cases.

Simple String Configuration

For basic commands, use a simple string:

exec: {
  simple_task: 'echo "Hello World"'
}

Object Configuration

For advanced options, use an object:

exec: {
  advanced_task: {
    command: 'npm test',
    cwd: './packages/core',
    stdout: true,
    stderr: true,
    exitCodes: [0, 1],
    timeout: 30000
  }
}

Function Commands

For dynamic commands that accept command-line arguments:

exec: {
  dynamic_task: {
    cmd: function(environment, version) {
      return 'deploy --env=' + environment + ' --version=' + version;
    }
  }
}

Run with: grunt exec:dynamic_task:production:1.2.0

Custom Callbacks

For processing command output:

exec: {
  callback_task: {
    cmd: 'git log --oneline -10',
    callback: function(error, stdout, stderr) {
      if (error) {
        grunt.log.error('Git command failed: ' + error.message);
        return;
      }
      
      var commits = stdout.split('\n').filter(Boolean);
      grunt.log.writeln('Found ' + commits.length + ' recent commits');
      commits.forEach(function(commit) {
        grunt.log.writeln('  ' + commit);
      });
    }
  }
}

Input/Output Control

Comprehensive control over process stdin, stdout, and stderr.

Standard Output Configuration

// Enable stdout (default)
stdout: true

// Disable stdout
stdout: false

// Pipe stdout
stdout: 'pipe'

// Inherit from parent process
stdout: 'inherit'

// Ignore stdout
stdout: 'ignore'

Standard Error Configuration

// Enable stderr (default)
stderr: true

// Disable stderr
stderr: false

// Pipe stderr for processing
stderr: 'pipe'

// Inherit from parent process
stderr: 'inherit'

Standard Input Configuration

// Enable stdin interaction (experimental)
stdin: true

// Disable stdin (default)
stdin: false

// Inherit stdin from parent
stdin: 'inherit'

Stdio Shorthand

// Inherit all stdio from parent
stdio: 'inherit'

// Pipe all stdio
stdio: 'pipe'

// Ignore all stdio
stdio: 'ignore'

Process Control Options

Advanced options for controlling command execution behavior.

Working Directory

// Static working directory
cwd: '/path/to/directory'

// Dynamic working directory
cwd: function(arg1, arg2) {
  return './environments/' + arg1;
}

Exit Code Validation

// Single expected exit code (default: 0)
exitCode: 0

// Multiple allowed exit codes
exitCodes: [0, 1, 2]

// Allow any exit code
exitCodes: []

Timeout Configuration

// 30 second timeout
timeout: 30000

// No timeout (default)
timeout: 0

Process Termination

// Custom kill signal
killSignal: 'SIGKILL'

// Default termination signal
killSignal: 'SIGTERM'

Synchronous vs Asynchronous Execution

Control execution mode based on your needs.

Asynchronous Execution (Default)

exec: {
  async_task: {
    cmd: 'long-running-command',
    sync: false  // or omit (default)
  }
}

Synchronous Execution

exec: {
  sync_task: {
    cmd: 'quick-command',
    sync: true
  }
}

Output Processing and Buffering

Control how command output is handled and processed.

Encoding Options

// UTF-8 encoding (default)
encoding: 'utf8'

// Binary encoding
encoding: 'binary'

// Buffer objects (no string conversion)
encoding: 'buffer'

Buffer Size Limits

// Custom buffer size (200KB default)
maxBuffer: 1024 * 1024  // 1MB

// Unlimited buffering
maxBuffer: 0

Output Processing Example

exec: {
  process_output: {
    cmd: 'npm ls --json',
    encoding: 'utf8',
    callback: function(error, stdout, stderr) {
      if (error) {
        grunt.fail.warn('Command failed: ' + error.message);
        return;
      }
      
      try {
        var packageInfo = JSON.parse(stdout);
        grunt.log.writeln('Package: ' + packageInfo.name);
        grunt.log.writeln('Version: ' + packageInfo.version);
      } catch (e) {
        grunt.log.error('Failed to parse JSON output');
      }
    }
  }
}

Error Handling and Debugging

Comprehensive error handling with detailed logging options.

Verbose Logging

Enable verbose logging for debugging:

grunt exec:my_task --verbose

Verbose mode provides detailed information about:

  • Command parsing and arguments
  • Process configuration
  • Buffer settings
  • Execution environment
  • Process ID and exit codes

Error Scenarios

grunt-exec handles various error conditions:

exec: {
  error_handling: {
    cmd: 'potentially-failing-command',
    exitCodes: [0, 1],  // Allow exit code 1
    callback: function(error, stdout, stderr) {
      if (error) {
        if (error.code === 'ENOENT') {
          grunt.log.error('Command not found');
        } else if (error.message.includes('timeout')) {
          grunt.log.error('Command timed out');
        } else {
          grunt.log.error('Command failed: ' + error.message);
        }
        return;
      }
      
      // Process successful output
      grunt.log.ok('Command completed successfully');
    }
  }
}

Shell Configuration

Control shell behavior and compatibility across platforms.

Shell Options

// Use default shell (recommended for cross-platform)
shell: true

// Use specific shell
shell: '/bin/bash'

// Disable shell (direct command execution)
shell: false

Platform Considerations

grunt-exec handles platform differences automatically:

exec: {
  cross_platform: {
    cmd: process.platform === 'win32' 
      ? 'dir /b' 
      : 'ls -1',
    shell: true
  }
}

Environment Variables

Pass custom environment variables to commands.

exec: {
  with_env: {
    cmd: 'echo $NODE_ENV',
    options: {
      env: {
        NODE_ENV: 'production',
        API_KEY: process.env.API_KEY
      }
    }
  }
}

Common Use Cases

Build Automation

exec: {
  build: {
    cmd: 'npm run build',
    cwd: './client'
  },
  
  test: {
    cmd: 'npm test',
    exitCodes: [0, 1]  // Allow test failures
  },
  
  deploy: {
    cmd: function(env) {
      return 'docker build -t myapp:' + env + ' .';
    }
  }
}

Git Operations

exec: {
  git_status: 'git status --porcelain',
  
  git_commit: {
    cmd: function(message) {
      return 'git commit -m "' + message + '"';
    }
  },
  
  git_push: {
    cmd: 'git push origin main',
    callback: function(error, stdout, stderr) {
      if (error) {
        grunt.fail.warn('Push failed: ' + stderr);
      } else {
        grunt.log.ok('Push successful');
      }
    }
  }
}

File Operations

exec: {
  cleanup: {
    cmd: process.platform === 'win32' ? 'del /q *.log' : 'rm -f *.log',
    stdout: false,
    stderr: false
  },
  
  backup: {
    cmd: 'tar -czf backup.tar.gz ./src',
    timeout: 60000  // 1 minute timeout
  }
}

Development Server Management

exec: {
  dev_server: {
    cmd: 'npm run dev',
    stdio: 'inherit',  // Show server output
    timeout: 0         // No timeout for long-running server
  },
  
  stop_server: {
    cmd: process.platform === 'win32' 
      ? 'taskkill /f /im node.exe' 
      : 'pkill -f "npm run dev"',
    exitCodes: [0, 1]  // Allow if no process found
  }
}