Redirect mongo shell error to output - mongodb

I have a script that seeds my database, but I want to only redirect the stderr to the user.
I'm trying this:
echo "Seeding pokemon"
mongo mongodb_1:27017/pokemon pokemon.js > /dev/null 2>&1
But I'm not getting the error output.If I remove the redirection, the error outputs to my console.

Mongo Shell does not currently support separate output stream for errors.
Have can subscribe to SERVER-18643 to get notified once this is implemented.
Workaround suggested in the above ticket is to tag your output inside the Mongo Shell:
...
print("<STDOUT>")
print(multiline_json)
print("</STDOUT>")
print("<STDERR>")
print(multiline_json)
print("</STDERR>")
...
Then you can redirect to the correct output stream using the following script:
#!/bin/bash
COMMAND="mongo <args>"
OUTPUT=$(${COMMAND})
function STDERR {
cat - 1>&2
}
function STDFILE {
if [ -z "$1" ]; then
return
fi
cat - >> $1
}
WRITE_ERR=0;
for line in $OUTPUT; do
if [[ "$line" == "<STDERR>"* ]]; then
WRITE_ERR=1
continue
elif [[ "$line" == "</STDERR>"* ]]; then
WRITE_ERR=0
continue
fi
if [ "$WRITE_ERR" -eq "1" ]; then
printf "%s\n" "$line" | STDERR
else
printf "%s\n" "$line"
fi
done

Related

Validate commit message for a GitHub rebase and merge

I am looking for a way to validate commit message via a pre-receive hook.
I am able to validate it for squash and merge commit however, it does not work for GitHub rebase and merge.
set -e
zero_commit='0000000000000000000000000000000000000000'
msg_regex='<pattern_here>'
release_branches=( topic master )
exit_code=0
containsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}
while read oldsha newsha refname; do
short_current_branch="$(echo ${refname} | sed 's/refs\/heads\///g')"
if containsElement "${short_current_branch}" "${release_branches[#]}"; then
echo "${short_current_branch} is in ${release_branches[#]}"
else
echo "${short_current_branch} is not in ${release_branches[#]}"
echo "Skipping execution"
continue
fi
case ${oldsha},${newsha} in
*,${NULL_SHA1}) # it's a delete
any_deleted=true;;
${NULL_SHA1},*) # it's a create
new_list="$new_list $newsha";;
*,*) # it's an update
new_list="$new_list $newsha";;
esac
done
if [[ -z "$new_list" ]]
then
exit ${exit_code}
fi
commit_msg=()
git rev-list ${new_list} --not --all |
while read sha1; do
message=$( git log --max-count=1 --format=%B ${sha1} | head -1)
if ! echo "${message}" | grep -o "<regex_pattern>" ; then
echo "ERROR:"
echo "ERROR: Your push was rejected because commit: ${commit}"
echo "ERROR: is missing radar link in first line of below commit message:"
echo "ERROR: ${message}"
echo "ERROR:"
echo "ERROR: Please fix commit message and push again."
echo "ERROR: https://docs.github.com/en/enterprise-
server#2.21/github/committing-
changes-to-your-project/changing-a-commit-message"
echo "ERROR"
exit_code=1
fi
done
exit ${exit_code}

validate only alphabets using shell script in busybox

I want to validate a string which should only be Alphabets (Capital/Small). I can do it in Linux easily using Bash or Shell, but not able to validate in Busybox (OpenWRT). My piece of code is
...
#!/bin/sh
. /usr/share/libubox/jshn.sh
Info=$(cat /root/Info.json)
json_load "$Info"
json_get_var value plmn_description
echo "$value"
if [[ "$value" == [a-zA-Z] ]] ;then
echo "Valid"
else
echo "Invalid information"
fi
...
You can use case conditional construct like this:
case "$value" in
*[!a-zA-Z]*) echo invalid information ;;
*) echo valid
esac
Using Busybox awk:
$ busybox awk '{ # using busybox awk
for(i=1;i<NF;i++) # iterate all json record fields (not the last, thou)
if($i=="\"plmn_description\":" && $(i+1)~/^\"[a-zA-Z]+\",?$/) {
ret="Valid" # if "plmn_description": is followed by "alphabets"
exit # exit for performance
}
}
END {
print (ret?ret:"Invalid") # output Valid or Invalid
}' Info.json # process the json file
Output:
Valid

php prevent '`rm -rf ~/`;'

Good day guys.
The issue I am having is specifically with handling this specific input case.
A part of my project I need to do is to take argument though command line into a PHP script. for eg ./do_op_2.php "`rm -rf ~/`;" .
I have tried using escapeshellarg($argv[1]), escapesellcmd($argv[1]); but to no avail it still executes the command. I have tried iterating through the string looking for ` and ; before anything happens, it is still executed.
If there are any more specific questions please do ask, I am willing to give more information.
Code for those who are curious.
#!/usr/bin/php
<?php
unset($argv[0]);
$argv[1] = escapeshellarg($argv[1]);
$argv[1] = escapeshellcmd($argv[1]);
function add($a, $b)
{
if (is_numeric($a) && is_numeric($b))
return ($a + $b);
else
return (0);
}
function minus($a, $b)
{
if (is_numeric($a) && is_numeric($b))
return ($a - $b);
else
return (0);
}
function mult($a, $b)
{
if (is_numeric($a) && is_numeric($b))
return ($a * $b);
else
return (0);
}
function divide($a, $b)
{
if (is_numeric($a) && is_numeric($b))
return ($a / $b);
else
return (0);
}
function mod($a, $b)
{
if (is_numeric($a) && is_numeric($b))
return ($a % $b);
else
return (0);
}
function ft_split($str)
{
$ret = array_filter(preg_split('/\s+/', $str));
return ($ret);
}
if ($argc == 2)
{
$split = ft_split(trim($argv[1], " \t"));
if (is_numeric($split[0]) && is_numeric($split[2]))
{
if ($split[1] == "+")
echo add(trim($split[0], " \t"), trim($split[2], " \t")) . "\n";
else if ($split[1] == "-")
echo minus(trim($split[0], " \t"), trim($split[2], " \t")) . "\n";
else if ($split[1] == "*")
echo mult(trim($argv[0], " \t"), trim($split[2], " \t")) . "\n";
else if ($split[1] == "/")
echo divide(trim($split[0], " \t"), trim($split[2], " \t")) . "\n";
else if ($split[1] == "%")
echo mod(trim($split[0], " \t"), trim($split[2], " \t")) . "\n";
else
echo "Syntax Error\n";
}
else
echo "Syntax Error\n";
}else
echo "Incorrect Parameters\n";
?>
The only thing I can think of is command substitution (see also parameter substitution) - something which happens in bash and other shells. If this is what's going on, then your reporting of the situation is a little misleading (read on).
It's very unlikely that PHP will be doing this, it'll be done by the shell, and there is no way to modify your code to prevent this... It's a feature of the shell.
For example a variable, using ${...}:
$ FOO="test"
$ echo ${FOO}
test
It's also possible to run a command and use the output (stdout) as the value with $(...):
$ echo $(date)
Tue 2 Oct 12:02:59 BST 2018
Another variant of this is using backticks:
$ echo `date`
Tue 2 Oct 12:04:03 BST 2018
You've listed the following in your question:
./do_op_2.php '`rm -rf ~/`;'
The use of single quotes (') should prevent the shell from substituting the backticks:
$ echo '${FOO}'
${FOO}
$ echo '`date`'
`date`
But using double quotes (") will not prevent this:
$ echo "${FOO}"
test
$ echo "`date`"
Tue 2 Oct 12:05:17 BST 2018
I can only presume that you've reported single quotes, but actually used double quotes when you observed this behaviour. Your comment supports this theory.
For eg. ./do_op_2.php "`rm -rf test.doc`;" will delete test.doc instead of ignoring the command.

Code fails with stdin from SED

I have a bash script that finds files with particular extension and then pass the files into a function that checks every line in the file for only files that contain a library imported. For example:
function testing() {
while IFS='' read -r line; do
if [[ "$line" =~ .*log\" ]]; then
echo "log is imported in the file" $1
break
else
echo "log is not imported in the file" $1
break
fi
done < <(sed -n '/import (/,/)/p' "$1")
}
function main() {
for file in $(find "$1" -name "*.go"); do
if [[ $file == *test.go ]]; then
:
else
var1=$(testing $file)
echo "$var1"
fi
done;
}
main $1
The problem is the script works without the else block in the testing function but with the introduction of the else block in the testing function it just defaults to echoing the log is not imported in the file blah even if log is used in some of the files.
Any idea(s) on what is the problem?
Thanks.
Here is a sample input file:
package main
import (
"fmt"
"io/ioutil"
logger "log"
"net/http"
)
type webPage struct {
url string
body []byte
err error
}
...
And the output is basically to echo if log is imported or not.
You need to rewrite the logic of your testing function as it will only test the first line of the file. Indeed, each branch of the if [[ "$line" =~ .*log\" ]] has a break statement, so in practice, a break is reached whenever the first line is read.

How do I port a shell script to Perl?

This is a shell script , How do I accomplish the same thing in Perl?
prfile=~/sqllib/db2profile
profile()
{
if [ -f $prfile ] && [ "$prfile" != "" ];
then
. $prfile
else
read -p "Enter a valid Profile : " prfile
profile
fi
}
profile
Here it checks for the profile file , if found it executes it with . $prfile else it again asks user for the proper profile file
Update
#!/usr/bin/perl
use strict;
use warnings;
my $profile = "$ENV{'HOME'}/sqllib/db2proile";
# default profile
while (not -e $profile) { # until we find an existing file
print "Enter a valid profile: ";
chomp($profile = <>); # read a new profile
}
qx(. $profile);
This worked. I want the home directory to be dynamic rather than hardcoded as they differ for different machines. I'm just trying to accomplish with Perl what I have achieved with shell.
If I understand your objectives, I don't think you can use perl to accomplish this because perl will be running as a child process and it can not change the environment of your shell (it's parent process). Maybe this would work for you (untested, off the cuff)?
prfile=~/sqllib/db2profile
if [ -s "$prfile" ] ; then
. "$prfile"
else
while true ; do
read -p "Enter a valid Profile : " prfile
if [ -s "$prfile" ] ; then
. "$prfile"
break;
fi
done
fi