Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
781 views
in Technique[技术] by (71.8m points)

linux - Is it possible to write shell command within Pharo smalltalk?

Like in other programming language, is there a way of running linux shell command in Pharo smalltalk or a simple script ? I would like to have my Pharo image running a script that should be able to automate a tasks and return it to some value. I looked at almost all the documentation around and I couldn't find anything related. Maybe It does not allow such functionality.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Pharo does allow the OS interaction. The best way, in my eyes, is to use OSProcess (as MartinW already suggested).

Those that think it is a duplicate are missing this part:

... running a script that should be able to automate a tasks and return it to some value...

There is nothing about return value in the invoking shell commands from squeak or pharo

To get a return value you would do it the following way:

command := OSProcess waitForCommand: 'ls -la'.
command exitStatus.

If you print out the above code you will get most probably a 0 as success.

If you do an obvious error:

command := OSProcess waitForCommand: 'ls -la /dir-does-not-exists'.
command exitStatus.

You will get ~= 0 value in my case 512.

Edit adding more details to cover more ground

I agree with eMBee that a statement

return it to some value

is rather vague. I'm adding information about I/Os.

As you may know there are three basic IO: stdin, stdout, and stderr. These you need to interact with shell. I'll add these examples first then I'll get back to your description.

Each of them is represented by instance of AttachableFileStream in Pharo. For the above command you will get initialStdIn (stdin), initialStdOut (stdout), initialStdError (stderr).

To write into the terminal from Pharo:

  1. stdout and stderr (you stream string into terminal)

    | process |
    
    process := OSProcess thisOSProcess.
    process stdOut nextPutAll: 'stdout: All your base belong to us'; nextPut: Character lf.
    process stdErr nextPutAll: 'stderr: All your base belong to us'; nextPut: Character lf.
    

Check your shell you should see the output there.

  1. stdin - to get what you typed

    | userInput handle fetchUserInput |
    
    userInput := OSProcess thisOSProcess stdIn.
    handle := userInput ioHandle.
    "You need this in order to use terminal -> add stdion"
    OSProcess accessor setNonBlocking: handle.
    fetchUserInput := OS2Process thisOSProcess stdIn next.
    "Set blocking back to the handle"
    OSProcess accessor setBlocking: handle.
    "Gets you one input character"
    fetchUserInput inspect.
    

If you want to grab an output from the command into Pharo a resonable way is to use PipeableOSProcess which, as apparent from his name, can be used in conjunction with pipes.

Simple example:

| commandOutput |

commandOutput := (PipeableOSProcess command: 'ls -la') output.
commandOutput inspect.

More complex example:

| commandOutput |

commandOutput := ((PipeableOSProcess command: 'ps -ef') | 'grep pharo') outputAndError.
commandOutput inspect.

I like the use of outputAndError because of typos. If you have an incorrect command you will get the error message:

| commandOutput |

commandOutput := ((PipeableOSProcess command: 'ps -ef') | 'grep pharo' | 'cot') outputAndError.
commandOutput  inspect.

In this case '/bin/sh: cot: command not found'

That is about it.

Update 29-3-2021 The OSProcess works up to Pharo 7. It was not upgraded to work with the changes at Pharo 8 or newer.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...