macOs Nodejs open the terminal by passing the command to execute
Asked Answered
K

2

1

I have the following code that should open a terminal and run a command:

import { ChildProcess, spawn, ChildProcessWithoutNullStreams, ChildProcessByStdio } from 'child_process';
import { Writable, Readable } from 'stream';

const terminal: 
ChildProcessWithoutNullStreams | 
ChildProcessByStdio<Writable, Readable, Readable> |
ChildProcess = spawn('open', ['-b', "com.googlecode.iterm2"]);

terminal.on('spawn', () => {
  console.log("spawn_0")
  if (terminal.stdin) {
    console.log("spawn_1")
    terminal.stdin.write(`tail -n +1 -f ${cacheDir}/${nameFile}.txt\n`);
    terminal.stdin.end();
  }
});

terminal.on('open', () => {
  console.log("open_0")
  if (terminal.stdin) {
    console.log("open_1")
    terminal.stdin.write(`tail -n +1 -f ${cacheDir}/${nameFile}.txt\n`);
    terminal.stdin.end();
  }
});

currently when this code is run, this is printed in the console:

spawn_0
spawn_1

The terminal opens correctly, but the "ls" command does not execute.

Info:

I have a txt file, which is continuously updated. I have to make sure that when the user calls this part of code, the terminal chosen by the user is started, redirecting the file output to the terminal.

Kordula answered 17/11, 2023 at 11:25 Comment(4)
Is there a reason why you can't use fs to list the contents of a directory instead? That would be significantly more performant (at scale) and require way less code. Is ls a placeholder for something else that doesn't have any Node bindings (or a way to write them)? If so, it might make more sense if you're able to update your code to be a bit closer to representative of your actual use case.Vinita
@esqew: I updated the command with the part that I should use in a few words I should redirect the output of a text file that is continuously updated on the terminal. Tell me if I was clear.Kordula
You're missing the \n that would execute the command in the terminal in question. Duplicate of Nodejs Child Process: write to stdin from an already initialised processVinita
I corrected the question by putting it, however it still doesn't work. The terminal is invoked, but the command is not passed. Open event, is not invoked. Spawn event, is called, but stdin.write, doesn't work.Kordula
A
0

If you want to redirect the output of a continuously updated text file to the terminal, and you've specified that ls is a placeholder for the actual command you want to execute, and considering the challenges you've mentioned, let's try this code.

import { spawn } from 'child_process';
import * as fs from 'fs';

const terminal = spawn('open', ['-b', 'com.googlecode.iterm2']);

terminal.on('exit', (code, signal) => {
  console.log(`Child process exited with code ${code} and signal ${signal}`);
});

terminal.on('error', (err) => {
  console.error(`Error: ${err.message}`);
});

terminal.stdout?.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

terminal.stderr?.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

// Replace 'ls' with your actual command
const command = 'tail -n +1 -f /path/to/your/file.txt';

// Wait for iTerm2 to open before sending the command
setTimeout(() => {
  terminal.stdin?.write(`${command}\n`);
  terminal.stdin?.end();
}, 2000);

Here, I've replaced ls with a placeholder command (tail -n +1 -f /path/to/your/file.txt) that continuously outputs the contents of a text file. Make sure to replace /path/to/your/file.txt with the actual path to your continuously updated text file.

This modified code should open iTerm2, wait for 2 seconds, and then send the specified command to continuously display the contents of the text file in the terminal.

Adaline answered 17/11, 2023 at 19:38 Comment(1)
Thx, I tried the code again(I don't understand how it differs from before in logic), however the terminal is opened, but the command is not passed to the terminal. There is only the terminal, which does nothing.Kordula
A
0

I can't find ls command in your code. So I think when you said ls, you mean tail.

There is some issue in your code.

  1. You need to recieve data from stdout/stderr of subproccess, they are not redirect to your main process automatically.
  2. You need some code to prevent the code from exit. So the process can wait for the data to come, and show them.
  3. terminal.stdin.end() will kill your main process immediately.

By the way, I can't test open -b com.googlecode.iterm2 on my PC. So I change it to bash. I think it would work on com.googlecode.iterm2 too.

import { ChildProcess, spawn, ChildProcessWithoutNullStreams, ChildProcessByStdio } from 'child_process';
import { Writable, Readable } from 'stream';

const cacheDir = './res';
const nameFile = 'test';

const terminal: 
ChildProcessWithoutNullStreams | 
ChildProcessByStdio<Writable, Readable, Readable> |
ChildProcess = spawn('bash');

terminal.on('spawn', () => {
  console.log("spawn_0")
  if (terminal.stdin) {
    console.log("spawn_1")
    terminal.stdin.write(`tail -n +1 -f ${cacheDir}/${nameFile}.txt\n`);
    // 3. remove the following code to prevent process from exit
    // terminal.stdin.end();
  }
});

terminal.on('open', () => {
  console.log("open_0")
  if (terminal.stdin) {
    console.log("open_1")
    terminal.stdin.write(`tail -n +1 -f ${cacheDir}/${nameFile}.txt\n`);
    // 3. remove the following code to prevent process from exit
    // terminal.stdin.end();
  }
});

terminal.on('error', (err) => {
  console.log("error", err)
});

//1. redirect stdout to main process
terminal.stdout.on('data', (data) => {
  process.stdout.write(data);
});

//1. redirect stderr to main process
terminal.stderr.on('data', (data) => {
  process.stderr.write(data);
});

//2. block the process, prevent from exit
(async ()=>{
  await new Promise(() => {});
})();

Appling answered 12/12, 2023 at 4:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.