Run linux more command from a C file using fork and exec functions - fork

I used fp = popen("more","w"); fprintf(fp,"%s", my_data);to display my data with pagination,
When I run the same on Linux docker container (gcr.io/distroless/base:debug), popen fails with error "cannon allocate memory".
I am thinking of implementing the requirement using fork and exec or system.
My data to the "more" command is a char* variable my_data (not a file).
Can I implement the same using fork()+exec or fork()+system function calls?
If yes how can I pass my string my_data to the more command?

Related

difference between execute shell script directly and through pipe

my shell script called mongoLogin.sh as below:
#!/bin/sh
mongo
use demo
show tables
the function of above is logining mongo and show tables of database called demo.
if I execute it directly by:
sh mongoLogin.sh
it works. however if I execute it by this way as below:
cat mongoLogin.sh | sh
compared with execute directly, it will exit automatically, as well as I ctrl+c after execute it directly. It seemed the sh command after pipe will create a new subprocess, and this subprocess finish due to some reason.
Do there exist some method that I can achieve same result by execute script through pipe?
update:
when execute directly it seemed only the first command make effect, because following commands are mongo operations rather than shell commands. And when I execute it by pipe, all commands make effect, but it exit automatically.
the output of executing it through pipe as below:
xxx#xxxMacBook-Pro:~/Downloads$cat mongoLogin.sh | sh
MongoDB shell version v4.0.3
connecting to: mongodb://127.0.0.1:27017
Implicit session: session { "id" : UUID("43c55950-f9e2-49ca-a458-
611f8c71eae4") }
MongoDB server version: 4.0.3
switched to db demo
test
bye
Both variants don't work, because use demo is not a valid shell command.
I have not worked with mongo, but if the command accepts is input from stdin, you can try
mongo <<OGNOM
use demo
show tables
OGNOM
Make sure that the final OGNOM starts in the first column of your line!

Error while trying to run shell script using OS process sampler in jmeter

one.jmx file takes command line arguments so i am putting the long command to run one.jmx in a shell script(RUN_GET_CALLS.sh). Now i am using Two.jmx which calls One.jmx via the shell script using OS process sampler.
When i execute Two.jmx it is giving error
timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect
1548833794770,4,"Patient_""_id""",500,"Exception occurred whilst executing system call: java.io.IOException: Cannot run program ""bash /home/ubuntu/HSDP_Suit/TestSuite/JMX_files/RUN_GET_CALLS.sh"" (in directory ""/home/ubuntu/JMeter/apache-jmeter-5.0/bin""): error=2, No such file or directory",Patient 1-4,text,false,,0,0,6,6,null,0,0,0
I tried putting path in Working directory box also but it is not working
Your syntax is a little bit incorrect you should configure the OS Process Sampler as follows:
Command: /bin/bash
Working directory: /home/ubuntu/HSDP_Suit/TestSuite/JMX_files
Argument #1: -c
Argument #2: ./RUN_GET_CALLS.sh ${PROPERTY_FILE} ${RESOURCE} ${PARAMETERS_STRING} ${FILE_NAME} ${RESULT_FILE}
Example configuration screenshot:
As per bash man page
-c string
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.
More information: How to Run External Commands and Programs Locally and Remotely from JMeter

Writing Automated scripts to configure device

My requirement is like this:
I need to log in to a remote device (say Router/switch) and execute following commands.
telnet xx.xx.xx.xx
//give password here
sys
interface g x/x/x
shut
desc free-port
exit
There are Hundreds of devices for which I cannot waste time doing above damn thing 100 times. I need to write a automated script which does it. so My questions are as follows:
I use Windows system, so What is the best scripting language to be used : Ruby / shell script / perl ? (I was formerly ROR Developer, so i know Ruby, Linux terminal. Now I am working in networking domain. )
What I thought was : Put all Devices into an array and using for loop, call devices one by one and execute above said commands.
I don't have knowledge of scripting, so please guide me further. I don't know where to start from.
Step 1: decide the file structure of your program.
For example, this is the simplest structure
if_admin/
|--config.yml
|--run.rb
Step 2: write a config file or a bunch of config files that contain the different parts of the commands you need to run on the targets.
For example, you can use a yaml file like this:
xx.xx.xx.xx:
password: s3cret
router-shelf: x
slot: x
port: x
yy.yy.yy.yy:
...
Step 3: implement what you want to do
require 'yaml'
require 'net/telnet'
config = YAML.load_file('./config.yml')
config.each do |host, conf|
telnet = Net::Telnet.new('Host' => host)
telnet.login(conf['password'])
telnet.puts <<-CMD
sys
interface g #{conf['router-shelf']}/#{conf['slot']}/#{conf['port']}
shut
desc free-port
CMD
telnet.close
end
If you can use expect script , you are in luck.
#!/usr/bin/expect
set timeout 60
set cmds [list "ssh host1 ..." "ssh host2 ..." "ssh host3 ..."]
foreach cmd $cmds {
spawn -noecho bash -c $cmd
expect {
-re "password" {
exp_send "$env(PASS_WORD)\"
exp_continue
}
eof { wait } ; # at this time the last spawn'ed process has exited
}
}
Here is the rough idea of above script :-
set cmds [list.... will be used as list to store set of commands.
foreach will iterate though those commands
spawn will spawn process for each of the command. you can write multiple command with single telnet in bash, just break down commands using \ (backslash) so it is easily readable and extendable.
expect block will pass password whenever it encounter certain regex.
eof will wait till all commands in spawn process are finish.
set timeout -1 will keep loop running. i think default time for expect script is 10secs.
You can create one more foreach loop for host-list.
I think this will be enough to get you started for your automation process.
As to the question of "What is the best scripting language to be used", I would say go with one that does what you need and one that you're comfortable with using.
If you want to go with Perl, one module that you could use is Net::Telnet. Of course, you'll need Perl itself. I'd recommend using Strawberry Perl, which should already have Net::Telnet installed.
Another possible route is to use putty, which is a SSH and telnet client. You could combine that with TTY Plus, which provides an interface that uses tabs for different putty sessions. And it lets you issue commands to multiple putty sessions. This is one possibility that wouldn't involve a lot of code writing.

How to pretend to be a tty when trying to freebsd-update from a shell script?

We usually use a custom script to setup new FreeBSD machines after system installation, which installs tools from ports tree and sets up system environment.
we also need to automate update newly installed FreeBSD-8.2 machines to FreeBSD-8.2p3 by freebsd-update. As I know, freebsd-update doesn't allow me to execute it from a shell script without a "cron" option. So I try to preload a custom program to cheat freebsd-update:
${CAT} > /tmp/isatty.c <<EOF
int isatty(const int fd) { return 1; }
EOF
${CC} -shared -fPIC -o /tmp/isatty.so /tmp/isatty.c
${ENV} LD_PRELOAD=/tmp/isatty.so LESS="-E" ${FREEBSD_UPDATE} fetch install < /dev/null
with this tweak, I can sucessfully run freebsd-update from my custom script, but after the freebsd-installer fetched files from update server, I got this error message:
Fetching metadata signature for 8.3-RELEASE from update5.FreeBSD.org... done.
Fetching metadata index... done.
Fetching 2 metadata files... gunzip: standard input is a terminal -- ignoring
metadata is corrupt.
Do I have any chance to solve this?
You set up your LD_PRELOAD which will also be picked up by any and all processes that freebsd-update spawns. The better solution would be to create a modified version of freebsd-update that would allow you to run it from the command line without requiring user interaction.
This utility may be what you need: empty - run processes and applications under pseudo-terminal (PTY)
This way you should be able start freebsd-update from script.

mongo shell script won't let me include "use <database>"

32-bit mongo 2.0.1 on a windows XP machine
//script filename: test.js (one line shell script file to store a person)
db.cTest.save({Name: "Fred", Age:21});
run against database dbTest by entering the following 2 shell commands:
> use dbTest
switched to dbTest
> load("test.js")
So far, so good.
But if I try and include the "use" statement in the script it fails:
//script filename: test.js (including "use" statement)
use dbTest;
db.cTest.save({Name: "Fred", Age:21});
fails with error msg as follows:
> load("test.js")
SyntaxError: missing ; before statement
Mon Dec 19 11:56:31: Error: error loading js file temp.js (shell):1
Adding or removing semicolons to test.js doesn't seem to matter.
So how do you put a "use" directive into a mongo shell script?
In a mongo script you can use the db.getSiblingDB('new_db_name') to get a reference of a new database. So, it it not mandatory to give the database name in the command line. You can use the script.js:
db = db.getSiblingDB('new_db_name');
print(db);
// the rest of your code for database "new_db_name"
and the output of this script is (invoked with mongo script.js):
MongoDB shell version: 2.2.2
connecting to: test
sag
http://www.mongodb.org/display/DOCS/Scripting+the+shell
use dbname
This command does not work in scripted mode. Instead you will need to explicitly define the database in the connection (/dbname in the example above).
Alternately, you can also create a connection within the script:
db2 = connect("server:27017/otherdbname")
Well, it still is unfortunate that "load('file.js')" and "mongo file.js" don't actually use the same script interpreter as the interactive mongo shell. Opening the connection explicitly in the script is potentially a violation of the DRY principle because mongo already knows that information. What does work, though, is piping the file into mongo rather than passing its name on the command line:
mongo <file.js

Resources