Use Unix Executable File to Run Shell Script and MPKG File - macos

I have 2 shell scripts and 2 mpkg installer, I am trying to use an unix excitable file to run them all. here is the script I have, but it always has error message "No such file or directory" ?
#!/bin/sh
# Find the absolute script current path
path=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
sudo sh $path/join.sh
sudo sh $path/join2.sh
#/usr/sbin/installer -dumplog -verbose -pkg $path/“esetv8.mpkg" -target /
#/usr/sbin/installer -dumplog -verbose -pkg $path/“sccm.mpkg” -target /
exit 0
Thanks so much!

The most common issue when handling variables containing paths of directories and files is the presence of special characters such as spaces. To handle those correctly, you should always quote the variables, using double quotes. Better code would therefor be:
sudo sh "$path/join.sh"
sudo sh "$path/join2.sh"
It is also advised to wrap the variables using curly braces, this can also help to avoid unwanted issues. Resulting in following code:
sudo sh "${path}/join.sh"
sudo sh "${path}/join2.sh"
While this should work, it's also appropriate to mention that it's advised to check whether the files actually exist before executing them. Checking a file for existence can be done using -f and checking execute permission using -x. The proper code is therefor:
[ -f "${path}/join.sh" ] && [ -x "${path}/join.sh" ] && sudo sh "${path}/join.sh"
[ -f "${path}/join2.sh" ] && [ -x "${path}/join2.sh" ] && sudo sh "${path}/join2.sh"
Note that if you have a bunch of these, you'd be better off executing them using a for loop. Note also that -f becomes redundant when checking -x so better code would be:
[ -x "${path}/join.sh" ] && sudo sh "${path}/join.sh"
[ -x "${path}/join2.sh" ] && sudo sh "${path}/join2.sh"

Related

How to use lxc exc to issue multiple commands as specific user

My goal is to execute two commands in a specific folder as ubuntu from outside of it's lxc container.
I've tried a couple of things but I figured this example is the closest I have to working.
If I run
root#host$ lxc exec my-containter -- sudo --login --user ubuntu eval "cd /home/ubuntu/mydir && pwd && whoami && env && npm install && echo done"
I get an npm install error that can't find some module, but it looks like I'm the right user
However if I manually do it as two steps it does work... but I'm trying to put this in a bash script, so that I can keep doing operations on the host, so I think I need it as one.
root#host$ lxc exec my-containter -- sudo --login --user ubuntu
ubuntu#my-container$ eval "cd /home/ubuntu/mydir && pwd && whoami && env && npm install && echo done";
I discovered that my PATH environment variable is different in these two situations, the one that is failing is missing a specific path for nvm/npm. I tried exporting it during the eval command, but it seems like the resources available to me have already been found? What could I do to make the PATH variable populate the same way in the single line scenario?
PATH from 1-line (non-interactive)
PATH=/home/ubuntu/bin:/home/ubuntu/.local/bin:/home/ubuntu/bin:/home/ubuntu/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/snap/bin:/snap/bin
PATH from 2-lines (interactive)
PATH=/home/ubuntu/bin:/home/ubuntu/.local/bin:/home/ubuntu/.nvm/versions/node/v8.9.4/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/snap/bin
I've also noticed this nvm code at the bottom on my .bashrc file. From what I've read it sounds like the .bashrc file only gets executed in interactive mode.
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
The below command should do the job for you
lxc exec my-containter -- sudo --login --user ubuntu bash -ilc "cd /home/ubuntu/mydir && pwd && whoami && npm install && echo done"
The .bashrc file has below at the top
case $- in
*i*) ;;
*) return;;
This code prevents the rest of the part of .bashrc to be executed in case of a non-interactive bash. So to make it interactive you should add the -i flag

Execution on ./ not sh

this is part of my current code
#! /bin/bash
#Take no arguments in
#checks to see if home/deleted is in existence
#creates the directory or file if it is missing
**(line 15)** function checkbin(){
if [ ! -c "~/deleted" ]; then
mkdir -p ~/deleted
fi
if [ ! -f "~/.restore.info" ]; then
touch ~/deleted/.restore.info
fi
}
I can call this code properly using ./remove [ARGS]
however when I call using sh remove [ARGS]
I receive the following error remove: 15: remove: Syntax error: "(" unexpected
ls -l on the file -rwxr-x--x
Does unix support execution on both sh and ./ ?
when executing with ./ /bin/bash is used (as define in shebang) whereas sh may be another interpreter or a link to bash which can have a different behaviour depending on how it is called sh.
bash is derived from sh but has some specific syntax:
for example in sh Function Definition Command is
fname() compound-command[io-redirect ...]
without function keyword.
For more details
Bash
Posix shell
If you want your script to run in sh as well as in bash, you need to be writing to the POSIX shell standard.
In this case, that means not using the Bash function keyword:
checkbin(){
test -c "~/deleted" || mkdir -p ~/deleted
test -f "~/.restore.info" || touch ~/deleted/.restore.info
}
If you're writing portable shell, then it's a good idea to use #!/bin/sh as your shebang.
(BTW, I assume you're aware that "~/deleted" and ~/deleted are in no way alike?)

Getting test: too many arguments error while checking existence of directory in shell script

I am trying to write a shell script for extraction of .tar.gz file. I need to check first that if same directory is not present then extract the zip file. Otherwise do some thing else. Below is my shell script.
#!/bin/bash
INSTALL_DIR=$HOME/Test/LogShipper
LOGSTASH_PATH=logstash-2.3.2
LOGSTASH_FOLDER=$HOME/Test/LogShipper/logstash
LOGSTASH_BINARY=$LOGSTASH_PATH.tar.gz
ES_PATH=elasticsearch-2.3.2
ES_BINARY=$ES_PATH.tar.gz
KIBANA_VERSION=kibana-4.5.0
KIBANA_OS=darwin-x64
KIBANA_BINARY=$KIBANA_VERSION-$KIBANA_OS
echo Installing ELK stack into $INSTALL_DIR
mkdir -p $INSTALL_DIR
cd $INSTALL_DIR
if test [! -d "$LOGSTASH_FOLDER" ];
then
if test -s $LOGSTASH_BINARY
then
echo Logstash Zip Exists
echo Now installing...
echo Unpacking logstash...
tar zxf $LOGSTASH_BINARY $LOGSTASH_FOLDER
echo Unpacking Completed.
else
echo Downloading logstash 2.3.2
curl -O https://download.elasticsearch.org/logstash/logstash/$LOGSTASH_BINARY
fi
else
echo Logstash already installed.
fi
I am getting error test: too many arguments at line if test [! -d "$LOGSTASH_FOLDER" ];
You probably don't need to use test when using [] as it implicitly invokes the same during evaluation. Also include a space after open brace [.
if [ ! -d "$LOGSTASH_FOLDER" ];
You can explicitly use test command the following way, try
if ! test -d "$LOGSTASH_FOLDER"
If "$HOME" has any spaces in it, and were unquoted (as it is in the given code), that would cause the error in question. Suggest changing:
INSTALL_DIR=$HOME/Test/LogShipper
...
LOGSTASH_FOLDER=$HOME/Test/LogShipper/logstash
...
mkdir -p $INSTALL_DIR
...
cd $INSTALL_DIR
To:
INSTALL_DIR="$HOME"/Test/LogShipper
...
LOGSTASH_FOLDER="$HOME"/Test/LogShipper/logstash
...
mkdir -p "$INSTALL_DIR"
...
cd "$INSTALL_DIR"

Cannot Create Directories On Ubuntu With Bash Shell Script

I'm trying to run this bash shell script to create directories for vim syntax highlighting on Ubuntu 13.04 (via Vagrant 1.4.1 on Windows 7).
#!/usr/bin/env bash
basevim="$HOME/.vim"
ftdetect="${basevim}/ftdetect"
indent="${basevim}/indent"
syntax="${basevim}/syntax"
echo "Setting up VIM for syntax highlighting"
#Create directories for vim syntax highlighting
if [ ! -d "$basevim" ]; then
echo "Adding VIM syntax highlighting dirs"
mkdir "$basevim"
mkdir "$ftdetect"
mkdir "$indent"
mkdir "$syntax"
else
if [ ! -d "$ftdetect" ]; then
mkdir "$ftdetect"
fi
if [ ! -d "$indent" ]; then
mkdir "$indent"
fi
if [ ! -d "$syntax" ]; then
mkdir "$syntax"
fi
fi
This is executing as a provision.sh script for Vagrant so as far as I know it should run as root. I can see the echo'd message so it's taking the first branch. But for the life of me I can't seem to get this to work; no complaints but the directories don't get created. If I set those variables on an interactive prompt, I need to do sudo mkdir ftdetect (etc.) to get the directories created. Strangely I don't need to sudo to get the .vim directory created--at least that's what I recall.
I tried
if [ ! -d "${basevim}" ]; then
but that didn't do anything. I also tried
basevim="{$HOME}/.vim"
--also no dice. Any thoughts of what I may be missing? As I say, as far as I know it shouldn't be necessary to sudo on a provisioning script on Vagrant. I can tell the script is getting run because those echo'd messages are getting output.
Your script could be replaced by
mkdir -p "$HOME/.vim"/{ftdetect,indent,syntax}
As for the directories not appearing... Where are you looking for them?
Running this as root would create them in root's home directory, /root/, and not in the user's home directory /home/username. When in doubt, use absolute path names (and chown as needed afterwards).

path of running bash script found when re-runs as sudo

The following code checks if you have root authority, then runs the script again with it :
CMDLN_ARGS="$#" # Command line arguments for this script (if any)
export CMDLN_ARGS
func_check_for_sudo() {
if [ ! $( id -u ) -eq 0 ]; then
echo "You may be asked for your login password for [`whoami`]." ;sleep 1
LAUNCH="`dirname \"${0}\"`"
exec sudo -S su -c ${LAUNCH}/$(basename ${0}) ${CMDLN_ARGS}
exit ${?}
fi
}
Where things are going wrong is when I place this script in a "$HOME/bin" folder or something so I can just launch it without the path. It gives me the error "No such file or directory". I need the script to get that information and correctly pass it to exec.
My question is this: how do I get the /path/to/script_name from within a script correctly when it is called without the path? To recap, I'm calling MY_SCRIPT insead /path/to/MY_SCRIPT which breaks my script because it has to check for root authority and run again if you don't have it.
Basically the line of code in question is this where ${0} is the script name (with path if you called it with one):
exec sudo -S su -c ${0} ${CMDLN_ARGS}
There are a couple of problems here:
Finding the path to the script. There are a couple of easy ways to do this: use "$BASH_SOURCE" instead of $0; or simply take advantage of the fact that (at least by default), sudo preserves $PATH, so sudo "$0" ... will resolve the script fine.
The second is that the script doesn't preserve its arguments properly. Spaces within arguments will be mistaken for breaks between arguments, and wildcards will be erroneously expanded. This is because CMDLN_ARGS="$#" mushes all the arguments together separated by spaces, and then ${CMDLN_ARGS} re-splits on spaces (maybe not the same way) and also expands wildcards.
Here's my take at correcting the problems. Note that putting the handler in a function just adds a layer of unnecessary complication, so I just put it inline. I also used sudo's -p option to clean up the prompting slightly.
if [ $( id -u ) -ne 0 ]; then
exec sudo -p "Login password for %p: " "$0" "$#"
exit $?
fi

Resources