In Windows when I double-click a Batch script, it will automatically open a terminal window and show me what's happening. If I were to double-click a bash script in Linux, a terminal window does not open to show me what is happening; it runs in the background. I have seen that one can use one script to launch another script in a new terminal window with x-terminal-emulator -e "./script.sh", but is there any bash command I can put into the same (one) script.sh so that it will open a terminal and show me what's happening (or if I need to answer y/n questions)?
You can do something similar to what Slax
developers do in their bootinst.sh:
#!/usr/bin/env sh
#
# If you see this file in a text editor instead of getting it executed,
# then it is missing executable permissions (chmod). You can try to set
# exec permissions for this file by using: chmod a+x bootinst.sh
#
# Scrolling down will reveal the actual code of this script.
#
# if we're running this from X, re-run the script in konsole or xterm
if [ "$DISPLAY" != "" ]; then
if [ "$1" != "--rex" -a "$2" != "--rex" ]; then
konsole --nofork -e /bin/sh $0 --rex 2>/dev/null || xterm -e /bin/sh $0 --rex 2>/dev/null || /bin/sh $0 --rex 2>/dev/null
exit
fi
fi
# put contents of your script here
echo hi
# do not close the terminal immediately, let user look at the results
echo "Press Enter..."
read junk
This script would run correctly both when started in graphical
environment and in tty. It tries to restart the script inside
konsole and xterm and but if it doesn't find neither of them it
will simply run in the background.
Related
I'm currently writing a bash script that would create multiple shell instances (with screen command) and execute a subprogram.
The problem is when I try to interrupt the subprogram, it interrupts the screen instance too. I already searched for trap command on internet with SIGINT but I don't really know how to use it in this case.
Here is my code to show you how do I create the screen:
#!/bin/bash
#ALL PATHS ARE DECLARED HERE.
declare -A PATHS; declare -a orders;
PATHS["proxy"]=/home/luna/proxy/HydraProxy; orders+=( "proxy" )
PATHS["bot"]=/home/luna/bot; orders+=( "bot" )
#LAUNCH SERVERS
SERVERS=/home/luna/servers
cd "$SERVERS"
for dir in */; do
d=$(basename "$dir")
PATHS["$d"]="$(realpath $dir)"; orders+=( "$d" )
done
for name in "${orders[#]}"; do
if ! screen -list | grep -q "$name"; then
path="${PATHS[$name]}"
cd "$path"
screen -dmS "$name" ./start.sh
echo "$name CREATED AT $path"
sleep 2
else
echo "SCREEN $name IS ALREADY CREATED"
fi
done
Could you help me more to find a solution please ? Thank you very much for your time.
Each of your screen instances is created to run a single command, start.sh. When this command terminates, for instance when you interrupt it, the screen will have done its job and terminate. The reason for this is that screen runs shell scripts directly in a non-interactive shell, rather than spawning a new interactive shell and running it there.
If you wanted to run start.sh inside an interactive shell in each screen, you'd do something like this:
screen -dmS "$name" /bin/bash -i
screen -S "$name" -X stuff "./start.sh^M"
The ^M is needed as it simulates pressing enter in your shell within screen.
If you use this, then when you interrupt a script within screen, you will still be left with an interactive prompt afterward to deal with as you see fit.
I have a script where it will check if background_logging is true, if it is then I want the rest of the script to run in a new detached screen.
I have tried using this: exec screen -dmS "alt-logging" /bin/bash "$0";. This will sometimes create the screen, etc. but other times nothing will happen at all. When it does create a screen, it doesn't run the rest of the script file and when I try to resume the screen it says it's (Dead??).
Here is the entire script, I have added some comments to explain better what I want to do:
#!/bin/bash
# Configuration files
config='config.cfg'
source "$config"
# If this is true, run the rest of the script in a new screen.
# $background_logging comes from the configuration file declared above (config).
if [ $background_logging == "true" ]; then
exec screen -dmS "alt-logging" /bin/bash "$0";
fi
[ $# -eq 0 ] && { echo -e "\nERROR: You must specify an alt file!"; exit 1; }
# Logging script
y=0
while IFS='' read -r line || [[ -n "$line" ]]; do
cmd="screen -dmS alt$y bash -c 'exec $line;'"
eval $cmd
sleep $logging_speed
y=$(( $y + 1 ))
done < "$1"
Here are the contents of the configuration file:
# This is the speed at which alts will be logged, set to 0 for fast launch.
logging_speed=5
# This is to make a new screen in which the script will run.
background_logging=true
The purpose of this script is to loop through each line in a text file and execute the line as a command. It works perfectly fine when $background_logging is false so there are no issues with the while loop.
As described, it's not entirely possible. Specifically what is going on in your script: when you exec you replace your running script code with that of screen.
What you could do though is to start screen, figure out few details about it and redirect your console scripts in/output to it, but you won't be able to reparent your running script to the screen process as if started there. Something like for instance:
#!/bin/bash
# Use a temp file to pass cat's parent pid out of screen.
tempfile=$(tempfile)
screen -dmS 'alt-logging' /bin/bash -c "echo \$\$ > \"${tempfile}\" && /bin/cat"
# Wait to receive that information on the outside (it may not be available
# immediately).
while [[ -z "${child_cat_pid}" ]] ; do
child_cat_pid=$(cat "${tempfile}")
done
# point stdin/out/err of the current shell (rest of the script) to that cat
# child process
exec 0< /proc/${child_cat_pid}/fd/0
exec 1> /proc/${child_cat_pid}/fd/1
exec 2> /proc/${child_cat_pid}/fd/2
# Rest of the script
i=0
while true ; do
echo $((i++))
sleep 1
done
Far from perfect and rather messy. It could probably be helped by using a 3rd party tool like reptyr to grab console of the script from inside the screen. But cleaner/simpler yet would be to (when desired) start the code that should be executed in that screen session after it has been established.
That said. I'd actually suggest to take a step back and ask, what exactly is it that you're trying to achieve and why exactly would you like to run your script in screen. Are you planning to attach/detach to/from it? Because if running a long term process with a detached console is what you are after, nohup might be a bit simpler route to go.
I'm trying to write a script that sets up my programming environment by taking as an argument the name of the project(directory) I want to open
so for example: ./my_script.sh sample_app
And here is the script so far:
#!/bin/bash
wmctrl -s 0
sublime &
sleep 2
wmctrl -s 1
google-chrome &
sleep 2
wmctrl -s 2
Dir="$echo /home/biTNumb/Projects/ruby/workspace/$1"
echo $Dir
gnome-terminal --window-with-profile=Guard -e ls &
#gnome-terminal -e cd /home/biTNumb/Projects/ruby/workspace/$1 && bundle exec guard &
#gnome-terminal -e cd /home/biTNumb/Projects/ruby/workspace/$1 && rails s &
The problem arises when the script executes:
gnome-terminal --window-with-profile=Guard -e ls &
I get the message The child process exited normally with status 0.:
I can't use the terminal after (I can only close it) and the message hides some part of the output. And yet, I have already created a profile and set the When command exits dropdown menu to 'Hold the terminal open'...
** I left the comments in the script so you can get the idea of what I'm trying to do
To execute multiple commands in the same gnome-terminal window, use semicolons ; as separators like below:
gnome-terminal -- bash -c "command 1; command 2; ...; bash;"
The last command bash starts the command-line interpreter so that the terminal doesn't exit at the end (use $shell instead of bash for a more general solution).
This way you won't need to define a profile with the option Hold the terminal open when command exits and you won't get the message The child process exited with status 0 (which hide some parts of the output).
Here is what you might write (I use backslashes \ to split lines):
gnome-terminal -- bash -c \
" ls ;\
cd /home/biTNumb/Projects/ruby/workspace/$1 && bundle exec guard ;\
cd /home/biTNumb/Projects/ruby/workspace/$1 && rails s;\
$bash;"
How do you run a shell script in a new terminal in Linux from a terminal like "start test.bat" in Windows, also it should be working in the console mode.
Here's a simple example to get you started:
To write a shell script, do this on your command prompt:
echo -e '#!/bin/sh\n echo "hello world"' > abc.sh
This writes:
#!/bin/sh
echo "hello world"
To a file called abc.sh
Next, you want to set it to executable by:
chmod +x abc.sh
Now, you can run it by:
./abc.sh
And you should see:
hello world
On your terminal.
To run it in a new terminal, you can do:
gnome-terminal -x ./abc.sh
or, if it's xterm:
xterm -e ./abc.sh
Here's a list of different terminal emulators.
Alternatively, you just run it in your current terminal, but background it instead by:
./abc.sh &
I came here wanting to figure out how to make a script spawn a terminal and run it self in it, so for those who want to do that I figured out this solution:
if [ ! -t 0 ]; then # script is executed outside the terminal?
# execute the script inside a terminal window with same arguments
x-terminal-emulator -e "$0" "$#"
# and abort running the rest of it
exit 0
fi
For gnome try this.
Replace ls with the command you want to run
gnome-terminal -x sh -c "ls|less"
I hope this is what you want
As of January 2020, the -e and -x option in gnome-terminal still run properly but throw out the following warnings:
For -e:
# Option “-e” is deprecated and might be removed in a later version
of gnome-terminal.
# Use “-- ” to terminate the options and put the command line to
execute after it.
For -x:
# Option “-x” is deprecated and might be removed in a later version
of gnome-terminal.
# Use “-- ” to terminate the options and put the command line to
execute after it.
Based on that information above, I confirmed that you can run the following two commands without receiving any warning messages:
gnome-terminal -- /bin/sh -c '<your command>'
gnome-terminal -- ./<your script>.sh
I hope this helps anyone else presently having this issue :)
#!/bin/sh
SERVER=$1
RCON=$2
echo "$SERVER"
echo "$RCON"
sudo -u flash screen -r $SERVER -X stuff "$RCON"`echo -ne '\015'`
Guys do you see something wrong with this code? The main concept in the script is to push a command to a opened screen session.
In particular, it's expected to execute a command into opened screen session.
The script echoes the two vars, but when I open the screen, the command $RCON isn't executed.
replaced
#!/bin/sh
with
#!/bin/bash