How to execute shell script with default parameters - bash

I'm not sure if the title explain the real problem.
I have a shell script load_config.shusing bash shell. This script will load the configuration. Before starting to load the configuration, it prompt the user "Do you want to load all configurations? Y/N ?". If the user choose "N" it does a different job with many questions prompting.
Now the real problem is; I have added this script to run in Makefile as below. My idea is to load all the configuration when I say make install, but then the script would prompt the user. I now donot want the script to prompt and it should take defaul 'Y' and install all configuration. How do I make this happen ?
.load_cfg.done : %
#echo -e "\n* Loading configuration $<"
$(PIN_HOME)/cfg/load_config.sh $<
touch $#
Shell : BASH
OS : LINUX

Use the yes command, in order to send a certain string into a user prompt.
For example, say your script looks like this:
$ cat loadConfig.sh
#!/bin/bash
read -p "Load all configuration? " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
then
echo "Loading all configuration"
else
echo "Not loading all configuration"
fi
Pipe yes into your script:
$ yes | loadConfig.sh
Loading all configuration

Related

Why can [ -x file ] be false even after chmod 777 file?

I'm an italian student trying to study bash. I have a question. I've to solve this following bash script
#!/bin/bash
echo hello
if [ -x "$namefile" ] ; then
echo "file $namefile exists"
else
echo " file $namefile doesn't exists"
fi
Reading your posts I understand that -x means if the file exists and is executable is true.
Now I have created a file with all permissions for all with chmod 777 file and I try to launch the script but the result is "File doesn't exists". Why?
This is a reverse engineering exercise and I can't modify the script.
If you don't want to modify your script, set the variable when calling the script:
namefile=myfile.txt ./sestoscr
(assuming that sestoscr is the name of the script you posted, and that the script has execute permission, and that myfile.txt is the name of the file you want to test using your script).
A more flexible solution would be to change the test in your script to
if [ -x "${namefile:=$1}" ] ; then
This still allows you to invoke the script via a change in environment (as outline above), but you also can call it using an explicit parameter,
./sestoscr myfile.txt
However, in this case I would give the positional parameter priority over the environment (because this is what most users would expect), and write it as:
namefile=${1:-$namefile}
if [ -x "$namefile" ]; ...
With this approach, if a parameter is supplied, it uses the parameter, and if none is supplied, it uses the environment variable namefile.

How to use STDOUT inside /etc/ssh/sshrc without breaking SCP

I want to call a program when any SSH user logs in that prints a welcome message. I did this by editing the /etc/ssh/sshrc file:
#!/bin/bash
ip=`echo $SSH_CONNECTION | cut -d " " -f 1`
echo $USER logged in from $ip
For simplicity, I replaced the program call with a simple echo command in the example
The problem is, I learned SCP is sensitive to any script that prints to stdout in .bashrc or, apparently, sshrc. My SCP commands failed silently. This was confirmed here: https://stackoverflow.com/a/12442753/2887850
Lots of solutions offered quick ways to check if the user is in an interactive terminal:
if [[ $- != *i* ]]; then return; fi link
Fails becase [ is not linked
case $- in *i* link
Fails because in is not recognized?
Use tty program (same as above)
tty gave me a bizarre error code when executed from sshrc
While all of those solutions could work in a normal BASH environment, none of them work in the sshrc file. I believe that is because PATH (and I suspect a few other things) aren't actually available when executing from sshrc, despite specifying BASH with a shebang. I'm not really sure why this is the case, but this link is what tipped me off to the fact that sshrc is running in a limited environment.
So the question becomes: is there a way to detect interactive terminal in the limited environment that sshrc executes in?
Use test to check $SSH_TTY (final solution in this link):
test -z $SSH_TTY || echo $USER logged in from $ip

Pass user inputs from one script to another during runtime

I have a requirement where ScriptA.sh has commands to ask for User's inputs and perform a set of actions. I want to automate this by creating another script which will read the questions asked from output of ScriptA.sh and provide the necessary values in runtime.
ScriptA.sh as follows :-
echo "Enter the CR Number"
read varnamecr
echo "CR Number is" $varnamecr
echo "Loading the config set. Choose Option From Below set
1.JAN
2.FEB
3.MAR"
read optionchoosen
echo "Option Choosen is :" $optionchoosen
echo "Will run the script/load configuration is this Ok ?[y/N]"
read userinput
echo "Proceed further, User has pressed ->"$userinput"<--Key"
How to write the second script to achieve this. Tried spawn and few other commands in the second script, but no luck. Please help me with this.
Since you're not specifying any shell in your tag, this is a possible, albeit crude, solution in ksh. It's using the coprocess capability of that shell (pretty sure it's not supported in bash although please don't quote me on that one)
#!/bin/ksh
./ScriptA.sh |&
while read -p Dummy; do
print $Dummy
case $Dummy in
"Enter the CR Number")print -p "CR123456"
;;
"3.MAR")print -p "3"
;;
"Will run the script"*)print -p "y"
;;
esac
done
The output gives :
Enter the CR Number
CR Number is CR123456
Loading the config set. Choose Option From Below set
1.JAN
2.FEB
3.MAR
Option Choosen is : 3
Will run the script/load configuration is this Ok ?[y/N]
Proceed further, User has pressed ->y<--Key
Will input remain same everytime? If so you can create wrapper of this script to provide required input.
cat wrapper
./ScriptA.sh <<!
123
2
y
!

using environment variables in service script

I am facing an issue using environment variables in my service script.
In my services script, i am using an environmental variable i.e. INSTALL_DIR whose value may vary on different system. I have to get the installation directory from $INSTALL_DIR and then i have to start the service. when i am running the service script the environment variable is not sourced at all.
Is it possible to source the installation directory from INSTALL_DIR environment variable. another option i can think is dynamically creating the service script using INSTALL_DIR environment variable.
echo "INSTALL DIR: ${INSTALL_DIR}"
name=`basename $0`
pid_file="/var/run/$name.pid"
get_pid() {
cat "$pid_file"
}
is_running() {
[ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1
}
Start()
{
echo "Starting Application"
if is_running; then
echo "[`get_pid`] Already Started"
else
if [ -z "$user" ]; then
nohup $INSTALL_DIR/bin/application 2>&1 &
else
nohup sudo -u "$user" $cmd 1> $INSTALL_DIR/bin/application 2>&1 &
fi
echo $! > "$pid_file"
if ! is_running; then
echo "Unable to start, see logs"
exit 1
fi
echo "[`get_pid`] Started"
fi
}
I am trying to run the application using following command
service application start
In my services script ... I have to get the installation directory from $INSTALL_DIR and then i have to start the service.
Your question isn't really about shell scripting, but about your system's startup. Unfortunately that process varies by Linux distribution, and tends to be poorly documented.
For example, man service says, service runs a System V init script or upstart job in as predictable an environment as possible, removing most environment variables and with the current working directory set to /., but man upstart says:
$ man -k upstart
upstart: nothing appropriate.
Not only that, but the service manpage specifically lists the environment variables a script will start with. Needless to say, yours isn't among them.
The traditional approach to parameterizing startup scripts is to put the information in a known file, normally in /etc, and reference that file in the script. In your case, you could do something like:
INSTALL_DIR=$(cat /etc/my-install-dir.cfg)
and then proceed accordingly.
There might be ways to coerce your startup to support other environment variables. But, sooner or later, the information you need has to be stored somewhere on the filesystem. It seems to me the simplest approach is to reserve a filename to hold that information, and read that file directly.
Use this below code in your script.
if [[ -z "${INSTALL_DIR}" ]]; then
echo "INSTALL_DIR is undefined"
else
INSTALL_DIR=<<your installation directory>>
fi

Pass a variable in a shell script

I'm new to Unix...I have a shell script that calls sqlplus. I have some variables that are defined within the code. However, I do not feel comfortable having the password displayed within the script. I would appreciate if someone could show me ways on how to hide my password.
One approach I know of is to omit the password and sqlplus will
prompt you for the password.
An approach that I will very much be interested in is a linux
command whose output can be passed into the password variable. That
way, I can replace easily replace "test" with some parameter.
Any other approach.
Thanks
#This is test.sh It executes sqlplus
#!/bin/sh
export user=TestUser
export password=test
# Other variables have been ommited
echo ----------------------------------------
echo Starting ...
echo ----------------------------------------
echo
sqlplus $user/$password
echo
echo ----------------------------------------
echo finish ...
echo ----------------------------------------
You can pipe the password to the sqlplus command:
echo ${password} | sqlplus ${user}
tl;dr: passwords on the command line are prone to exposure to hostile code and users. don't do it. you have better options.
the command line is accessible using $0 (the command itself) through ${!#} ($# is the number of arguments and ${!name} dereferences the value of $name, in this case $#).
you may simply provide the password as a positional argument (say, first, or $1), or use getopts(1), but the thing is passwords in the arguments array is a bad idea. Consider the case of ps auxww (displays full command lines of all processes, including those of other users).
prefer getting the password interactively (stdin) or from a configuration file. these solutions have different strengths and weaknesses, so choose according to the constraints of your situation. make sure the config file is not readable by unauthorized users if you go that way. it's not enough to make the file hard to find btw.
the interactive thing can be done with the shell builtin command read.
its description in the Shell Builtin Commands section in bash(1) includes
-s Silent mode. If input is coming from a terminal, characters are not echoed.
#!/usr/bin/env bash
INTERACTIVE=$([[ -t 0 ]] && echo yes)
if ! IFS= read -rs ${INTERACTIVE+-p 'Enter password: '} password; then
echo 'received ^D, quitting.'
exit 1
fi
echo password="'$password'"
read the bash manual for explanations of other constructs used in the snippet.
configuration files for shell scripts are extremely easy, just source ~/.mystuffrc in your script. the configuration file is a normal shell script, and if you limit yourself to setting variables there, it will be very simple.
for the description of source, again see Shell Builtin Commands.

Resources