Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be able to execute shell commands #1937

Open
Angelk90 opened this issue Sep 20, 2023 · 6 comments
Open

Be able to execute shell commands #1937

Angelk90 opened this issue Sep 20, 2023 · 6 comments
Labels
enhancement New feature or request Needs: Triage 🔍

Comments

@Angelk90
Copy link

Angelk90 commented Sep 20, 2023

Summary

Being able to execute shell commands for example using child_process would be very useful.

Basic Example

const { exec } = require("child_process");

...
          exec("ls -la", (error, stdout, stderr) => {
            if (error) {
                console.log(`error: ${error.message}`);
                return;
            }
            if (stderr) {
                console.log(`stderr: ${stderr}`);
                return;
            }
            console.log(`stdout: ${stdout}`);
        });
@Angelk90
Copy link
Author

Angelk90 commented Oct 2, 2023

Hi @Saadnajmi , can you tell me something about it?

@Saadnajmi
Copy link
Collaborator

This sort of issue comes up in our repo a lot. Here's why it's currently not possible:

exec, child_process, along with many other Javascript packages are node modules, but not react native style native modules. They are re different ways to execute native code from Javascript that are currently incompatible.

Node modules are with the Node-API, while React Native modules are written with either the legacy native module system, or as turbo modules, the latter of which uses a layer called JSI to talk to native code.

This issue is with React Native in general (you wouldn't be able to run your above code on iOS or Android), but it is more pronounced on our desktop platform, where one expects all their favorite node APIs to work.

There is a project from @vmoroz (feel free to correct my mistakes describing) to refactor the JSI layer mentioned to support the node-api, allowing node modules to work with react native turbo modules. Then, your request would be something that is possible. Unfortunately, I don't have an ETA for when that project will land, or whether it would get adopted by React Native or React Native macOS. It's currently getting prototyped on React Native windows.

@Angelk90
Copy link
Author

Angelk90 commented Oct 2, 2023

@ospfranco: Do shell commands work on sol?
It seems to me that you have done something with JSI, do you think it is possible?

@Saadnajmi : How come this command works /sbin/ping:

import {spawn, kill} from 'react-native-childprocess'

  useEffect(() => {
    const fetchData = async () => {
      cmdID = await spawn('/sbin/ping', ['google.com'], {
          pwd: "/",
          stdout: (output) => {
              console.log('>>>', output)
          }
      });
      console.log(cmdID)
    }
  
    fetchData()
      .catch(console.error);
  }, [])

However, any different command does not work.
Like ls or pwd don't work.

Maybe a set of commands found in /sbin work.

@ospfranco
Copy link

Simple native implementation and binding

https://github.com/ospfranco/sol/blob/1b638b1facf61520c13cd47dfa62544363a078d6/macos/sol-macOS/lib/SolNative.swift#L92

https://github.com/ospfranco/sol/blob/1b638b1facf61520c13cd47dfa62544363a078d6/macos/sol-macOS/lib/ShellHelper.swift

Probably won't work with Sandboxing enabled though. So no, React Native probably shouldn't/can't implement this, also huge security vunerability for bad actors.

@Saadnajmi
Copy link
Collaborator

@ospfranco: Do shell commands work on sol?

It seems to me that you have done something with JSI, do you think it is possible?

@Saadnajmi : How come this command works /sbin/ping:

import {spawn, kill} from 'react-native-childprocess'



  useEffect(() => {

    const fetchData = async () => {

      cmdID = await spawn('/sbin/ping', ['google.com'], {

          pwd: "/",

          stdout: (output) => {

              console.log('>>>', output)

          }

      });

      console.log(cmdID)

    }

  

    fetchData()

      .catch(console.error);

  }, [])

However, any different command does not work.

Like ls or pwd don't work.

Maybe a set of commands found in /sbin work.

react-native-childprocess seems to be a rewrite of child_process as a react native module is why it works

@Angelk90
Copy link
Author

Angelk90 commented Oct 2, 2023

@okwasniewski , @Saadnajmi , @ospfranco : I don't know but it seems like maybe it works like this:

import { spawn, kill } from 'react-native-childprocess';
....
const [pwd, setPwd] = useState(undefined);

  useEffect(() => {
    let cmdID;
    const shell = async () => {
      cmdID = await spawn('/bin/sh', ['-c','ls'], {
        pwd: '/Users/',
        stdout: (output) => {
          const paths = output.split('\n').filter(Boolean).filter(val => val !== "Shared");
          if(paths.length === 1) setPwd(`/Users/${paths[0]}/Desktop`)
        },
        stderr: (output) => console.log('stderr:', output),
        terminate: (output) => console.log('terminate:', output),
      });
    };

    shell().catch(console.error);
    return () => {
      kill(cmdID);
    };
  }, []);

  useEffect(() => {
    if(pwd === undefined) return
    let cmdID;
    const shell = async () => {
      cmdID = await spawn('/bin/sh', ['-c','ls'], {
        pwd,
        stdout: (output) => {
          console.log(output.split('\n').filter(Boolean))
        },
        stderr: (output) => console.log('stderr:', output),
        terminate: (output) => console.log('terminate:', output),
      });
    };

    shell().catch(console.error);
    return () => {
      kill(cmdID);
    };
  }, [pwd]);

Let me know what you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Needs: Triage 🔍
Projects
None yet
Development

No branches or pull requests

3 participants