Skip to the content.

SSHScript v2.0 CLI(Draft)

Last Updated on 2023/11/1

Back to Index

The SSHScript package includes a CLI named sshscript. It is installed with the SSHScript package. To check if it is available, open a terminal and type sshscript. If it is not available, check the $PATH environment variable. (details)

sshscript [paths [paths …]]

Executing dollar-syntax scripts (.spy)

This is for executing python scripts written in dollar-syntax of the SSHScript. For example:

## file: hello.spy
$hostname
print(f'localhost is named as "{$.stdout}"')

Then, execute the hello.spy in a shell console, like this:

$ sshscript hello.spy

You can run multiple .spy files too.

For example, suppose that you have another .spy file named “world.spy”. Then you can run it like this:

$ sshscript hello.spy world.spy

sshscript –folder FOLDER

Executing dollar-syntax scripts in a folder

You can put .spy files into a folder and use –folder to address them. The next example runs test/hello.spy and test/world.spy.

$ sshscript --folder test hello.spy world.spy

The next example runs all .spy files in the test folder.

$ sshscript --folder test

“glob” could be used too. For example:

$sshscript --folder unittest base.spy "b*.spy"

This would run unittest/base.spy, unittest/b1.spy, unittest/b2.spy. But uittest/a1.spy is excluded.

sshscript --run-order

Ensuring the sequence of execution

Suppose you want to run .spy files in a folder, like this:

$sshscript --folder unittest base.spy "b*.spy"

Since all .spy files are executed one-by-one. You want to make sure the executing sequence is correct.

You can use the –run-order option. For example

$sshscript --run-order --folder unittest base.spy "b*.spy"

With this option, sshscript will not execute them, it just shows them in order of execution.

sshscript –folder FOLDER –ext SSHSCRIPTEXT

Changing default .spy to your own extension

If .spy is what you want, you can specify your own extension. The next example runs all .myspy files in the test folder.

$sshscript --unittest --ext .myspy

sshscript --debug

Finding problems

This would set the debuging level to logging.DEBUG (10).

$sshscript --debug hello.spy 

If you prefer more details, you can set debuging level to 8

$sshscript --debug 8 hello.spy 

Please note that, for level 8, the logging message contains all data sent to ssh channel. Some credential information, such as passwords, could be included in logging messages.

sshscript --script

Knowning what is exactly executed by Python

With this option, the sshscript would not execute script files. It would output the parsed and converted python script from those .spy files. This is for debugging purposes.

$sshscript --script hello.spy 
# output is converted "regular python script" of hello.spy, no execution.

From SSHScript 2.0, You can run the output script too. For example:

$ sshscript --script hello.spy > hello-parsed.spy

Then

$ sshscript --script hello-parsed.spy

When the sshcript runs the hello-parsed.spy, it would not parse it again.

sshscript --verbose

Checking the outputs on stdout and stderr

With this option, the sshscript would dump stdout and stderr to console.

$sshscript hello.spy --verbose

You can set the prefix of dumping lines for stdout or stderr: For stdout, it is os.environ[’VERBOSE_STDOUT_PREFIX’] , default is 🟩▏. For stderr, it is os.environ[’VERBOSE_STDERR_PREFIX’] , default is 🟨.

_ export _ = [str …]

When you have many *.spy files to run. You can export local variables in a file to files after it. For example:

#content of file: 0.spy
import json, pickle

myfolder = os.path.dirname(__file__)

def saveToJson(obj,filename):
    # ⬇if the "myfolder" is not exported,
    # ⬇ declare that it is a global also works
    # global myfolder  
    filepath = os.path.join(myfolder,filename)
    with open(filepath,'w') as fd:
        json.dump(obj,fd)

def saveToPickle(obj,filename):
    filepath = os.path.join(myfolder,filename)
    with open(filepath,'w') as fd:
        pickle.dump(obj,fd)

# we have to export "myfolder" too
# because "myfolder" is used in "saveToJson".
__export__ = ['savetoJson','myfolder']
#content of file: 1.spy

# "saveToJson" is available in 1.spy because it is exported by 0.spy
saveToJson({'hello':'world'})

# But "saveToPickle" is undefined
try:
    saveToPickle({'hello':'world'})
except NameError:
    pass
# You can test above 0.spy and 1.spy by
$sshscript 0.spy 1.spy

_ export _ = ‘*’

When export is ‘*’, then all locals() are exported. For example:

#content of file: 0.spy
import json, pickle

def saveToJson(obj,filename):
    filepath = os.path.join(os.path.dirname(__file__),filename)
    with open(filepath,'w') as fd:
        json.dump(obj,fd)

def saveToPickle(obj,filename):
    filepath = os.path.join(os.path.dirname(__file__),filename)
    with open(filepath,'w') as fd:
        pickle.dump(obj,fd)

__export__ = '*'  #⬅ look here
#content of file: 1.spy
# saveToJson is available
saveToJson({'hello':'world'})

# saveToPickle is available too.
saveToPickle({'hello':'world'})
# You can test above 0.spy and 1.spy by
$sshscript 0.spy 1.spy

The export can help to organize files better. You can put utilization functions or common variables in 0.spy and use them from 1.spy to 9.spy.

Single Session of Execution

If you run many files sequentially. They would run in a single ssh session. Which means that if it has ssh-connected to a remote host in 0.spy, then 1.spy would also run in the same remote host. For example:

#content of file: 0.spy
$hostname
print($.stdout) #⬅ would be the localhost

# let's connect to "host"
$.connect(’user@host’)

# Please note that 
# we do not __export__ anything at the end of 0.spy.
#content of file:1.spy
$hostname
print($.stdout) #⬅ would be the "host"
$.close()  #⬅ would close the connetion to "user@host"
# You can test above 0.spy and 0.spy by
$sshscript 0.spy 1.spy