I get an error (on line: sh up.sh) running the following:
#!/bin/bash
# Install angular components
echo "Installing Angular Components..."
cd angApp
npm install
# Install Server components
echo "Installing Backend Components..."
cd ..
cd APIServer
# go back to main dir
cd ..
# ask to see if we should launch server
echo "Do you want to launch the server now? Enter (yes/no) "
read shouldLaunch
# Launch if requested. Otherwise end build
if [ "$shouldLaunch" == "yes" ]; then
echo "Great! Launching the servers for you..."
sh up.sh
else
echo "No problem..."
echo "you can launch the server by doing ./up.sh"
echo "bye!"
fi
How do I run the up.sh script?
If the up.sh file is in the same directory as the file containing the code above then you can do
echo "Great! Launching the servers for you..."
$(dirname $0)/up.sh
The variable $0 is the path of the current script, dirname strips off the last segment of the path, and $(...) turns the output of dirname into a string.
To avoid cd-ing mess, simply run the parts in subshells, like:
#!/bin/bash
(
# Install angular components - in shubshell
echo "Installing Angular Components..."
cd angApp
npm install
)
(
# Install Server components - again in subshell
echo "Installing Backend Components..."
cd APIServer
#do something here
)
# go back to main dir
#cd .. #not needed, you're now in the parent shell...
# ask to see if we should launch server
echo "Do you want to launch the server now? Enter (yes/no) "
read shouldLaunch
# Launch if requested. Otherwise end build
if [ "$shouldLaunch" == "yes" ]; then
echo "Great! Launching the servers for you..."
sh up.sh
else
echo "No problem..."
echo "you can launch the server by doing ./up.sh"
echo "bye!"
fi
Related
I've bash script to load docker images once the application is installed (postinstall script).
Using command manually on the terminal is working, but from postinstall script getting:
docker: command not found
Tried, executing docker with absolute path (which docker) adding the path variable of docker (execute PATH=\usr\bin\docker:$PATH)
Is there something wrong with my macOS or script is wrong.
Original script:
I m checking the macOS chip and then using command docker info trying if docker is installed if its installed loading the images from the working directory otherwise installing docker first and then loading images.
#!/bin/bash
#
#
#
CheckVar=`which docker`
echo "$CheckVar"
if [[ `sysctl machdep.cpu.brand_string` == *"Intel"* ]]
then
if [[ `$CheckVar info` == *"Client"* ]];
then
echo "Mac Chip is Intel"
echo "Docker found!"
cd $Home/$DSTROOT/App
echo "Redirected to working dir.."
sudo `$CheckVar load -i app.tar`
echo "Success"
else
echo "Mac Chip is Intel"
echo "Docker not found installing"
cd $Home/$DSTROOT/App
echo "Redirected to working dir.."
sudo hdiutil attach IntelDocker.dmg
sudo /Volumes/Docker/Docker.app/Contents/MacOS/install
sudo hdiutil detach /Volumes/Docker
sudo `$CheckVar load -i app.tar`
echo "Success"
fi
else
if [[ `$CheckVar info` == *"Client"* ]];
then
echo "Mac Chip is AppleSilicon"
echo "Docker found!"
cd $Home/$DSTROOT/App
echo "Redirected to working dir.."
sudo `$CheckVar load -i app.tar`
echo "Success"
else
echo "Mac Chip is AppleSilicon"
echo "Docker not found installing"
cd $Home/$DSTROOT/App
echo "Redirected to working dir.."
sudo hdiutil attach IntelDocker.dmg
sudo /Volumes/Docker/Docker.app/Contents/MacOS/install
sudo hdiutil detach /Volumes/Docker
sudo `$CheckVar load -i app.tar`
echo "Success"
fi
fi
Any solutions? been trying to solve this issue past 3 days.
First make sure your PATH is valid. It should contain the directory which the docker executable is stored in. Not the absolute path to the executable. Also, execute PATH is not how you set the value. You use export
export PATH=/usr/bin:$PATH
Change your tests from:
[ `$CheckVar info` == *"Client"* ]] to [ "$CheckVar" ]
from man test:
-n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
The CheckVar variable is empty in the case where docker wasn't found on the system. Reset it in your else statements after installing docker.
sudo /Volumes/Docker/Docker.app/Contents/MacOS/install
sudo hdiutil detach /Volumes/Docker
CheckVar=`which docker`
sudo $CheckVar load -i app.tar
So my main goal is to access Tshock console so i could run some commands on the server directly.
From what i found as soon as the command to run the server is executed there is no option to get back to the console so:
I'd like to run the server in screen mode.
Dockerfile is basicly running some bash script but i'm getting errors when i'm trying to add "screen" to it. I'm getting "bootstrap.sh: 33: bootstrap.sh: Syntax error: "fi" unexpected (expecting "then")
Entering script"
I've tried everything i could found on google but nothing works :( This is my first time when i'm doing any scripting in bash so i would be grateful for understanding :)
Here is the link to original repo: https://github.com/ryansheehan/terraria/blob/master/tshock/bootstrap.sh
I would be glad for any hints on how to make this script working or if there is any other simplier option to access the console of the server :)
I've added extra line in dockerfile to download screen so it looks like that now:
FROM alpine:3.11.6 AS base
RUN apk add --update-cache \
unzip
# add the bootstrap file
COPY bootstrap.sh /tshock/bootstrap.sh
ENV TSHOCKVERSION=v4.4.0-pre12
ENV TSHOCKZIP=TShock4.4.0_Pre12_Terraria1.4.0.5.zip
# Download and unpack TShock
ADD https://github.com/Pryaxis/TShock/releases/download/$TSHOCKVERSION/$TSHOCKZIP /
RUN unzip $TSHOCKZIP -d /tshock && \
rm $TSHOCKZIP && \
chmod +x /tshock/TerrariaServer.exe && \
# add executable perm to bootstrap
chmod +x /tshock/bootstrap.sh
FROM mono:6.8.0.96-slim
LABEL maintainer="Ryan Sheehan <rsheehan#gmail.com>"
# documenting ports
EXPOSE 7777 7878
# env used in the bootstrap
ENV CONFIGPATH=/root/.local/share/Terraria/Worlds
ENV LOGPATH=/tshock/logs
ENV WORLD_FILENAME=""
# Allow for external data
VOLUME ["/root/.local/share/Terraria/Worlds", "/tshock/logs", "/plugins"]
# install nuget to grab tshock dependencies
RUN apt-get update -y && \
apt-get install -y nuget && \
apt-get install -y screen
# rm -rf /var/lib/apt/lists/* /tmp/*
# copy game files
COPY --from=base /tshock/ /tshock/
# Set working directory to server
WORKDIR /tshock
# run the bootstrap, which will copy the TShockAPI.dll before starting the server
ENTRYPOINT [ "/bin/sh", "bootstrap.sh" ]
And here is my modified code for bootstrap.sh :
#!/bin/sh
echo "Entering script"
if [ -z "$STY" ];then
echo "Opening screen mode ..."
exec screen -dm -S terraria bin/bash "$0"
else
echo "Continuing with script in screen mode"
echo "\nBootstrap:\nworld_file_name=$WORLD_FILENAME\nconfigpath=$CONFIGPATH\nlogpath=$LOGPATH\n"
echo "Copying plugins..."
cp -Rfv /plugins/* ./ServerPlugins
WORLD_PATH="/root/.local/share/Terraria/Worlds/$WORLD_FILENAME"
if [ -z "$WORLD_FILENAME" ]; then
echo "No world file specified in environment WORLD_FILENAME."
if [ -z "$#" ]; then
echo "Running server setup..."
else
echo "Running server with command flags: $#"
fi
mono --server --gc=sgen -O=all TerrariaServer.exe -configpath "$CONFIGPATH" -logpath "$LOGPATH" "$#"
else
echo "Environment WORLD_FILENAME specified"
if [ -f "$WORLD_PATH" ]; then
echo "Loading to world $WORLD_FILENAME..."
mono --server --gc=sgen -O=all TerrariaServer.exe -configpath "$CONFIGPATH" -logpath "$LOGPATH" -world "$WORLD_PATH" "$#"
else
echo "Unable to locate $WORLD_PATH.\nPlease make sure your world file is volumed into docker: -v <path_to_world_file>:/root/.local/share/Terraria/Worlds"
exit 1
fi
fi
fi
After removing empty spaces as #KamilCuk suggested the script is running but the screen doesn't seem to be working.
Here is the output from console:
PS D:\TerrariaServer\Source\terraria\tshock> docker run --rm -p 7777:7777 -v D:/TerrariaServer/World:/root/.local/share/Terraria/Worlds --name="terraria" terraria-image -world /root/.local/share/Terraria/Worlds/TestWorld.wld
Entering screen mode
+ [ -z ]
+ echo Entering screen mode
+ screen -d -m -S terraria bin/bash bootstrap.sh
+ echo Screen mode activated
+ echo Continuing with script in screen mode
+ echo \nBootstrap:\nworld_file_name=\nconfigpath=/root/.local/share/Terraria/Worlds\nlogpath=/tshock/logs\n
+ echo Copying plugins...
+ cp -Rfv /plugins/* ./ServerPlugins
Screen mode activated
Continuing with script in screen mode
Bootstrap:
world_file_name=
configpath=/root/.local/share/Terraria/Worlds
logpath=/tshock/logs
Copying plugins...
cp: cannot stat '/plugins/*': No such file or directory
+ WORLD_PATH=/root/.local/share/Terraria/Worlds/
+ [ -z ]
+ echo No world file specified in environment WORLD_FILENAME.
+ [ -z -world /root/.local/share/Terraria/Worlds/TestWorld.wld ]
+ echo Running server with command flags: -world /root/.local/share/Terraria/Worlds/TestWorld.wld
+ mono --server --gc=sgen -O=all TerrariaServer.exe -configpath /root/.local/share/Terraria/Worlds -logpath /tshock/logs -world /root/.local/share/Terraria/Worlds/TestWorld.wld
No world file specified in environment WORLD_FILENAME.
Running server with command flags: -world /root/.local/share/Terraria/Worlds/TestWorld.wld
Error Logging Enabled.
TerrariaAPI Version: 2.1.0.0 (Protocol v1.4.0.5 (230), OTAPI 1.4.0.5)
[TShock] Info Config path has been set to /root/.local/share/Terraria/Worlds
[TShock] Info Log path has been set to /tshock/logs
TShock was improperly shut down. Please use the exit command in the future to prevent this.
TShock 4.4.0.0 (Go to sleep Patrikkk, Icy, Chris, Death, Axeel, Zaicon, hakusaro, Zack, and Yoraiz0r <3) now running.
AutoSave Enabled
Backups Enabled
Welcome to TShock for Terraria!
TShock comes with no warranty & is free software.
You can modify & distribute it under the terms of the GNU GPLv3.
[Server API] Info Plugin TShock v4.4.0.0 (by The TShock Team) initiated.
Terraria Server v1.4.0.5
Resetting game objects 1%
Resetting game objects 2%
Resetting game objects 3%
...
I'm not directly seenig major issues with your entrypoint script. But I want provide some steps I would do to hopefully resolve these kind of issues:
Avoid the line f [ -z "$#" ].
See here why.
Suggestion: f [ -z "$*" ]
Also this line is problematic too: echo "Running server with command flags: $#"
See here why.
Suggestion: echo "Running server with command flags: $*"
Sometimes it can help, to enter the container and "play around". This allows you to work in your docker container like you would do in any normal Linux shell.
Have a look at the -interactive, -i option for docker run.
Example
If you want to start your container, you can run e. g. run a bash (...or sh, or whatever shell you are using):
docker run -it <img_name> <arguments> bash
This also works with exec when your container is already running and you want to enter it.
docker exec -it <container_id> bash
Try the bash -x option when invoking your entrypoint script to get a verbose output. Sometimes it helps finding the error.
ENTRYPOINT [ "/bin/bash", "-x" "bootstrap.sh" ]
I have some easy backup script to tar, xz and save to SMB share some folders and want to use variable ($invocation) for a part of the command.
Unfortunately, when script runs it remembers that the variable $location is empty and a result of it is no backup
(xz: /mnt/backupMatrix//2020-06-05T00-27.tar.xz: No such file or directory).
I do know why it's not working, but how to do it correctly?
How to "reload" variable $invocation (with freshly set $location) just before it's launch, WITHOUT hardcoding whole invocation to the function?
Code below.
#! /bin/bash
invocation="xz --threads=8 -z -9 -v -v - > /mnt/backupMatrix/$location/$(date +%Y-%m-%dT%H-%M).tar.xz"
function mcuser2
{
#backup mcuser2
location="mcuser2"
echo "setting var location to: $location"
echo "Stopping minecraft2.service"
sudo systemctl stop minecraft2.service
echo "Stopped minecraft2.service"
echo "Starting taring mcuser2"
# --exclude='/home/mcuser2/world'
tar cpf - --exclude='/home/mcuser2/plugins/dynmap/web/tiles' /home/mcuser2/ | $invocation
echo "Completed taring mcuser2"
echo "starting minecraft2.service"
sudo systemctl start minecraft2.service
echo "started successfully minecraft2.service"
}
case "$1" in
mcuser2)
mcuser2
;;
esac
Since you set location unconditionally in the function, the simplest approach is to move that line from the function and place it before you set invocation.
An alternative is to use more variables:
: "${XZ:=xz}"
: "${XZOPTIONS:=--threads=8 -z -9 -v -v -}"
: "${TSTAMP:=$(date +%Y-%m-%dT%H-%M)}"
: "${BASEDIR:=/mnt/backupMatrix}"
: "${TAR:=tar}"
: "${TAROPTIONS:=-cpf -}"
STARTDIR="/home/mcuser2" # $HOME?
EXCLUDE="--exclude=$STARTDIR/plugins/dynmap/web/tiles"
function mcuser2
{
#backup mcuser2
location="mcuser2"
echo "setting var location to: $location"
echo "Stopping minecraft2.service"
sudo systemctl stop minecraft2.service
echo "Stopped minecraft2.service"
echo "Starting tarring mcuser2"
$TAR $TAROPTIONS - "$EXCLUDE" "$STARTDIR" |
$XZ $XZOPTIONS > "$BASEDIR/$location/$TSTAMP.tar.xz"
echo "Completed tarring $STARTDIR"
echo "starting minecraft2.service"
sudo systemctl start minecraft2.service &&
echo "started successfully minecraft2.service"
}
Warning: untested shell scripting.
I'd probably not include the full path in the archive (GNU tar drops the leading slash anyway); I'd cd to the start directory and specify . as the directory to be backed up — possibly use -C "$STARTDIR" on the tar command line. That would require me to alter the exclude option too, I expect, using a relative path instead of an absolute path.
You could also think of using shell arrays for the options lists.
I'm not convinced I'd use a function in this script; it doesn't really seem to help very much.
I'm just learning to write bash scripts.
I'm writing a script to setup a new server.
How should I go about testing the script.
i.e.
I use apt install for certain packages like apache, php etc. and then a couple of lines down there is an error.
I then need to fix the error and run it again but it will run all the install commands again.
The system will probably say the package is installed already, but what if there are commands which append strings to files.
If these are run again it will append the same string to the file a second time.
What is the best approach to write bash-scripts like this?
Can you do test runs which rollback everything after an error or end of the script?
Or even better to have the script continue from the line where the error occured the next time it is run?
I'm doing this on an Ubuntu 18.04 server.
it's a matter of how clear you want it to be to read it, but
[ -f .step01-done ] || your install command && touch .step01-done
[ -f .step02-done ] || your other install command && touch .step02-done
maybe a little easier to read:
if ! [ -f .step01-done ]; then
if your install command ; then
touch .step01-done
fi
fi
if ! [ -f .step02-done ]; then
if your other install command ; then
touch .step02-done
fi
fi
...or something in between.
Now, I would suggest creating a directory somewhere and maybe logging output from the commands to some file there (maybe tee it) but definitely putting all these files you are creating with touch there. That way if you start it from another directory by accident, it won't matter. You just need to make sure that apt-get or whatever you use actual returns false if it fails. It should.
You could even make a function that does it in a nice way...
#!/bin/bash
function do_cmd() {
if [ -f "$1.done" ]; then
echo "$2: skipping already completed step"
return 0
fi
echo -n "$2: "
$3 1> "$1.out" 2> "$1.err"
if $?; then
echo "ok"
touch "$1.done"
return 0
else
echo "failed"
echo -e "see \"$1.out\" and/or \"$1.err\" for details."
return 1
# could "exit 1" instead
fi
}
[ -d /root/mysetup ] || mkdir /root/mysetup
if ! [ -d /root/mysetup ]; then
echo "failed to find or create /root/mysetup directory
exit 1
fi
cd /root/mysetup
# ---------------- your steps go here -------------------
do_cmd prog1 "installing prog1" "apt-get install prog1" || exit 1
do_cmd prog2 "installing prog2" "apt-get install prog2" || exit 1
do_cmd startfoo "starting foo service" "service foo start" || exit 1
echo "all setup functions finished."
You would use:
do_cmd identifier "description" "command or function"
description
identifier: unique identifier used when files are generated:
identifier.out: standard output from command
identifier.err: standard error from command
identifier.done: created when command is successful
description: this is actually printed to the terminal when the step is being executed.
command or function: this is the actual command to run
not sure why stackoverflow forced me to format that last bit as code but w/e
I'm having trouble executing some files under a BASH script.
What I want is, when running the SCRIPT.SH, to check if the directory from which it's running is the right one. Which in this case it's /ROOT/OPENSOURCE . If it's not, then it asks if the user wants to move the directory into the correct place. Doing this by another script /OPENSOURCE/MODULES/MOVE.SH.
I have this variable to get the script launching dir:
spath="$( cd "$( dirname $0 )" && pwd )"
Now since the script will not be installed on the right directory, I need to run MOVE.SH which is in the MODULES directory inside OPENSOURCE. I can't get this done.
Code:
# check if script is on correct directory
if [ "$rpath" = "$spath" ]; then
Colors;
echo ${RedF}[x] [WAIT]${YellowF} Checking directory: ${Reset};
sleep 1
echo ${BlueF}[*] [Directory]:${GreenF} OK ${Reset};
else
Colors;
echo ${RedF}[x] [WAIT]${YellowF} Checking directory: ${Reset};
sleep 1
echo ${BlueF}[*] [Directory]:${RedF} FAILED: This may cause a script malfunction ${Reset};
read -p "[!] Move script directory to right directory {y|n}:" pass
if test "$pass" = "y"
then
echo ${BlueF}[*] [Directory]: ${GreenF}Ok. Moving script to new directory${Reset};
sleep 1
---- COMMAND WILL BE HERE ----
else
echo ${BlueF}[*] [Directory]: ${YellowF}Ok not moving ${Reset};
fi
fi
How can I do it ?
I'm not sure I 100% understand the question, but I think you might just be looking for the mysterious "." command, which will run another script.
Example:
test.sh:
#!/bin/bash
echo running other script $1
. $1
echo done
test2.sh:
#!/bin/bash
echo I am the other script
Run it:
> ./test.sh test2.sh
running other script test2.sh
I am the other script
done