How to run ssh with a multiline argument read from a file? - shell

I have Puppeteer installed in a Docker container and I want to access it from another container via SSH. The command I'm using looks like this:
$ sshpass -proot ssh root#puppeteer node -e "$(cat index.js)"
bash: -c: line 0: unexpected EOF while looking for matching `''
bash: -c: line 1: syntax error: unexpected end of file
index.js looks like this:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
args: [
'--no-sandbox',
'--disable-setuid-sandbox'
]
});
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
I can't figure out why it isn't working. Just for comparison (I can't use this approach in the final code) I tried it through docker-compose and it worked:
docker-compose exec puppeteer node -e "$(cat ../index.js)"
I know that I could first copy index.js to the puppeteer container using scp and then access it directly, but in general it seems that multiline arguments should be possible, how to make them work here?

Related

Fetch value from column name in unix

val=$(curl https://www.geeksforgeeks.org | tr '\n' ' ' | tr -s [[:space::]] | grep -E client_id -e publication_id)
I have a requirement to fetch the particular value from curl command:
Sample I/P:
client_id:"15647",publication_id:["151","152","153"]
Output:
publication_id:["151,"152","153"]
I want to use grep command to fetch publication_id values from curl command in unix and store in variable
One solution with nodejs, xidel, xpath and puppeteer, as said in comments, you need a js aware tool:
Javascript wget.js code (this is only to mimic wget, it's output only HTML, and the one generated by js too):
const puppeteer = require('puppeteer');
(async () => {
var url = process.argv[2];
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
const html = await page.evaluate(() => document.documentElement.outerHTML);
console.log(html);
browser.close();
})()
code:
node wget.js 'https://www.geeksforgeeks.org' |
xidel -e '//div[#id="g_id_onload"]/#data-client_id'
Output:
388036620207-3uolk1hv6ta7p3r9l6s3bobifh086qe1.apps.googleusercontent.com

History command isn't recognized as an internal command in child_process

I'm trying to make a hook for Github in js.
So I need to get the previous command, but child_process doesn't recognize the history command, which runs fine in my windows git bash.
This is the code I have
const { exec } = require("child_process");
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
exec('history 2', (err, res, er) => {
console.log(res)
});
history is no a program (not a binary or a script) but a command builtin into bash. You only can run it with bash — and only interactively:
$ bash -c "history 2"
(no output because it's non-interactive)
In a non-interactive session you have to read the history before using it:
$ bash -c "history -r && history 2"
the previous command
the last command
My advice is to use fc instead of history. With fc you can select one command to show. For example to get the previous command use index -2:
$ bash -c "history -r && fc -ln -2 -2"
the previous command

How to pass parameters to a script processed by ts-node

I just started ts-node utilizing. It is the a very convenient tool. Run time looks clear. But it does not work for CLI solutions. I can not pass arguments into a script compiled.
ts-node --preserve-symlinks src/cli.ts -- printer:A
It does not work. I am asking for a help.
You did not provide your script, so I can only guess at how you are extracting the arguments. This is how I have made it work with my own test script args.ts:
const a = process.argv[2];
const b = process.argv[3];
const c = process.argv[4];
console.log(`a: '${a}', b: '${b}', c: '${c}'`);
Called from package.json like this:
"scripts": {
"args": "ts-node ./args.ts -- 4 2 printer:A"
}
This will give me output like this:
a: '4', b: '2', c: 'printer:A'
command
ts-node ./test.ts hello stackoverflow
ts file
console.log("testing: >>", process.argv[2], process.argv[3]);
output
$ testing: >> hello stackoverflow
Happy coding
Try this:
node --preserve-symlinks -r ts-node/register src/cli.ts printer:A
NODE_OPTIONS
For the case of node options, in addition to -r ts-node/register mentioned at https://stackoverflow.com/a/60162828/895245 they now also mention in the docs the NODE_OPTIONS environment variable: https://typestrong.org/ts-node/docs/configuration/#node-flags
NODE_OPTIONS='--trace-deprecation --abort-on-uncaught-exception' ts-node ./index.ts
A quick test with:
main.ts
(async () => { throw 'asdf' })()
and run:
NODE_OPTIONS='--unhandled-rejections=strict' ts-node main.ts
echo $?
which gives 1 as expected.
Tested on Node v14.16.0, ts-node v10.0.0.

Capture output of a shell script inside a docker container to a file using docker sdk for python)

I have a shell script inside my docker container called test.sh. I would like to pipe the output of this script to a file. I can do this using docker exec command or by logging into the shell (using docker run -it) and running ./test.sh > test.txt. However, I would like to know how the same result can be achieved using the docker sdk for python. This is my code so far:
import docker
client = docker.APIClient(base_url='unix://var/run/docker.sock')
container= client.create_container(
'ubuntu:16.04', '/bin/bash', stdin_open=True, tty=True, working_dir='/home/psr', \
volumes=['/home/psr/data'], \
host_config=client.create_host_config(binds={
'/home/xxxx/data_generator/data/': {
'bind': '/home/psr/data',
'mode': 'rw',
},
})
)
client.start(container=container.get('Id'))
cmds= './test.sh > test.txt'
exe=client.exec_create(container=container.get('Id'), cmd= cmds,
stdout=True)
exe_start=client.exec_start(exec_id=exe, stream=True)
for val in exe_start:
print (val)
I am using the Low-Level API of the docker sdk. In case you know how to achieve the same result as above using the high level API, please let me know.
In case anyone else had the same problem, here is how I solved it. Please let me know in case you have a better solution.
import docker
client = docker.APIClient(base_url='unix://var/run/docker.sock')
container= client.create_container(
'ubuntu:16.04', '/bin/bash', stdin_open=True, tty=True,
working_dir='/home/psr', \
volumes=['/home/psr/data'], \
host_config=client.create_host_config(binds={
'/home/xxxx/data_generator/data/': {
'bind': '/home/psr/data',
'mode': 'rw',
},
})
)
client.start(container=container.get('Id'))
cmds= './test.sh'
exe=client.exec_create(container=container.get('Id'), cmd=cmds,
stdout=True)
exe_start=client.exec_start(exec_id=exe, stream=True)
with open('path_to_host_directory/test.txt', 'wb') as f: # wb: For Binary Output
for val in exe_start:
f.write(val)

Execute ssh shell script from npm command

I'm trying to write an npm script that will execute an ssh shell command. Currently it's working by executing an osascript command to open a Terminal window and run the command.
I'd like to change this to execute the command in the current terminal. The script is including both shelljs and executive. The script ends without anything happening when I use executive. With shelljs I get:
Pseudo-terminal will not be allocated because stdin is not a terminal.
the input device is not a TTY
The command being executed is: ssh -i [ssh-key] -t ubuntu#[ip-address] eval $(base64 -D <<< [command in base64])
The base64 command is sudo docker exec -i -t $(sudo docker ps -aqf "ancestor=' + containerName + '") /bin/bash
If I output the command and copy and paste it, it will work as expected, sshing into a remote machine and running a docker exec command.
If I remove the -t option I don't get the warning messages but there's no output in the console and the script hangs (I assume it's running the command in the background with no output). If I remove the eval ... part I get an output that looks like what you'd see when sshing into a server but without the input terminal.
What can I do to execute this command in the same terminal or in a new tab. If I have to use an osascript command to do this, that's fine as well. I'll be executing this command from the terminal in PhpStorm though.
Edit
Here's the block of code:
var execCommand = 'sudo docker exec -i -t $(sudo docker ps -aqf "ancestor=nginx") /bin/bash';
var buffer = new Buffer(execCommand);
var encoded = buffer.toString('base64');
var cmd = "ssh -i " + this.keyPath + " -t ubuntu#" + ip + " eval $(base64 -D <<< " + encoded + ") ";
shell.exec(cmd);
Edit 2
I can ssh into the machine successfully and get a command prompt but I'm getting a the input device is not a TTY error now when I add the eval command.
var docker_exec = 'sudo docker exec -it $(sudo docker ps -aqf "ancestor=' + containerName + '") /bin/bash';
var encoded = new Buffer(docker_exec).toString('base64');
var sshTerm = spawn('ssh', [
'-i',
this.keyPath,
'ubuntu#' + ip,
'eval',
'eval $(base64 -D <<< ' + encoded + ')'
], {
stdio: 'inherit',
shell: true
});
sshTerm.on('exit', function() {
process.exit(0);
});
I checked and it shelljs.exec is good for non TTY commands. For TTY based command you can use normal spawn method. Below is a sample code that works great for me
var spawn = require('child_process').spawn;
var sshTerm = spawn('ssh', ["vagrant#192.168.33.100", ""], {
stdio: 'inherit'
});
// listen for the 'exit' event
// which fires when the process exits
sshTerm.on('exit', function(code, signal) {
if (code === 0) {
// process completed successfully
} else {
// handle error
}
});

Resources