Server that provides an API to execute bash-scripts remotely on the server and store its outputs in the database.
API has a few endpoints:
/api/commands- GET - fetches all launched commands/api/get_command?id=<id>- GET - gets full indormation about command with provided ID
Result will be looking like that (empty values will be omitted):
[
{
"command_info": {
"id": id,
"command": "command1"
},
"input_info": {
"input": "input",
},
"outputs": {
"output": "output",
"errors": "errors"
},
"statuses": {
"exit_code": exit_code
}
},
{
"command_info": {
"id": id,
"command": "command2"
},
"input_info": {
"input": "input",
},
"outputs": {
"output": "output",
"errors": "errors"
},
"statuses": {
"exit_code": exit_code
}
}
]/api/launch- POST - launches new command on the server. Accepts request body:
{
"command": "echo $this_is_the_key | cat -",
"env": [
"key": "this_is_the_key",
"value": "this_is_the_value"
],
"input": "this_is_the_stdin",
"workdir": "/home"
}Only necessary parameter is command.
/api/cancel?id=<id>- POST - cancels execution of the command with provided ID
If command is long enough, then every 5 seconds its stdout and stderr updates and sends into the database.
If command was cancelled or there are some errors on the server - exit code of this command will be -1.
Database consists of 4 tables:
| field | type | key |
|---|---|---|
| id | SERIAL |
Primary Key |
| command | TEXT NOT NULL |
| field | type | key |
|---|---|---|
| id | SERIAL |
References commands (id) |
| input | TEXT |
|
| env | env_entry |
| field | type |
|---|---|
| key | TEXT |
| value | TEXT |
| field | type | key |
|---|---|---|
| id | SERIAL |
References commands (id) |
| output | TEXT |
|
| errors | TEXT |
| field | type | key |
|---|---|---|
| id | SERIAL |
References commands (id) |
| exit_code | INTEGER |
Upon succesful insertion into commands table appropriate amount of empty records are inserted into tables outputs and statuses.
Port for the database is 5432 and for the server is 8888.
docker-compose up- What is a script will be?
When we launching scripts or commands in the terminal we have a few stable envrionments:
- working directory
- environment variables
- command or script itself
- command's or script's stdin
- command's or script's stdout and stderr
So I decided to represent all of these things.
We also have an arguments that can be passed to the command or script but in terms of launching them through
bash -cthey are working a little odd.
- Which tables and how many of them should I be using?
In case of different API endpoints (for example - getting a list of launched commands) i needed to separate some of properties of the command. Thus for getting a list of all commands we need only commands themselves - the first and main table
commandsis defined.
inputstable was born logically - it is separated from outputs and statuses table.Outputs are tethered because they can be merged or redirected in script -
outputstable is born.And
statusestable is separated from all of them by meaning that command is finished and server will no longer gather command's outputs.
- How to launch everything?
In my opinion the simplest solution is docker-compose. I quite worked with it and it allows to start multiple services in one command, such as builder, database and runner itself.