Linux Shell script executed but not return to command prompt - linux

I have a script that runs one of the following line
sudo -u $USER $SUDOCMD &>>stdout.log
The sudo command is a realtime process that print out lots of stuff to the console.
After running the script each time, the script does not return to the command prompt. You have to press enter or ctrl + c to get back to the command prompt.
Is there a way to to do it automatically, so that I can get a return value from the script to decide whether the script runs ok or failed.
thanks.

What is probably happening here is that your script is printing binary data to the TTY rather than text to standard output/error, and this is hiding your prompt. You can for example try this:
$ PS1='\$ '
$ (printf "first line\nsecond line\r" > $(tty)) &>> output.log
The second command will result in two lines of output, the second one being "mixed in" with your prompt:
first line
$ cond line
As you can see the cursor is on the "c", but if you start typing the rest of the line is overwritten. What has happened here is the following:
You pressed Enter to run the command, so the cursor moved a line down.
The tty command prints the path to the terminal file, something like "/dev/pts/1". Writing to this file means that the output does not go to standard output (which is usually linked to the terminal) but directly to the terminal.
The subshell (similar to running the command in a shell script) ensures that the first redirect isn't overridden by the second one. So the printf output goes directly to the terminal, and nothing goes to the output log.
The terminal now proceeds to print the printf output, which ends in a carriage return. Carriage return moves the cursor to the start of the line you've already written to, so that is where your prompt appears.
By the way:
&>> redirects both standard output and standard error, contrary to your filename.
Use More Quotes™
I would recommend reading up on how to put a command in a variable

Related

Open new terminal window and execute bash file

I have written a bash script 'A' that executes some commands,but after complete execution of script 'A',I want another bash script 'B' which is stored on desktop to be executed new terminal window after execution of 'A' is completed.What command should I write at end of script 'A'?So that script 'B' is executed in new terminal window. I have tried many commands such as gnome-terminal and konsole both with their various arguments but I couldn't make it work.
Say two commands instead of Script A and Script B I use ls -lh and echo
xterm -e "ls -lh; read ;xterm -e \"echo \"Hello_World\"; read \""
read is given just to stimulate human interaction and you can see the terminal appearing and closing.

How to identify which REPL is running in the terminal?

I am trying to have my terminal title change depending on what that specific window is doing. So far I have the following which will update based on directory and server.
function settitle() {
if [[ -z "$ORIG" ]]; then
ORIG=$PS1
fi
TITLE="\[\e]2;$*:$(dirs -0)\a\]" #dirs -0 is like pwd but with ~/ instead of /home/user/
PS1=${ORIG}${TITLE}
}
PROMPT_COMMAND="settitle local" # local is the server name in this case
Now, sometimes I'm in the PHP (php -a) or MySQL (mysql -u user -ppass) REPL, and I'd like the title to reflect that instead of just being whatever directory I launched the REPL from.
The best I can figure is getting the last command somehow, then figuring out what the first word is, and running an if check in settitle(). I've tried everything from here and here among other places, and while I can usually get part of it to work in the command line, non of it works in settitle(). For example.
local:~$ echo 'foobar'
foobar
local:~$ !:0
echo
# I add echo !:0 to settitle()
local:~$ source .bashrc
!:0
local:~$
A note: It should be "source", or at least "echo" from before. !:0 does not recognize itself as a command so it will repeat the last real command over and over. The "!:0" being echoed is a literal string, not the results of the command. Additionally, saving to a var does not work, and just putting the command without trying to echo/save the result gives !:0: command not found.
I don't want to make this an XY problem, so if I am barking up the wrong tree here at any step of the process, please let me know. The goal is to be able to change the title of my terminal window if I enter an REPL. How can I identify when a command will enter me into one?
Note that PROMPT_COMMAND and similar shell features are not relevant when you're in a different REPL; from the point of view of the shell, the entire REPL session is one single command. The shell prompt doesn't show up again until you exit that REPL, and that's the point at which PROMPT_COMMAND and friends are activated.
One thing you can do is alias the command you use to start the REPL so that it sets the title of the window first:
alias phpa='setttitle PHP; php -a'
alias mysqli=`settitle MySQL; mysql -u "$USER"'
or something like that.
The sequence goes like this:
PROMPT_COMMAND runs.
The shell prints its prompt.
You type the command to start a REPL
You are in the REPL. The prompt you see is printed by the REPL, not the shell, which is not involved at this point. The shell is just hanging out waiting for you to exit the REPL; it's not printing any prompts, so it's not ever running PROMPT_COMMAND.
You type commands in the REPL. No matter how many you run, it's part of a single session that the shell sees as a single command.
You exit the REPL.
PROMPT_COMMAND runs.
The shell prints its prompt.

Disable pagination on the command line

I am trying to write a script using the python module pexpect that will connect to a server and execute commands like you are typing at the command line.
So for example, you can have something like:
child = pexpect.spawn('/usr/bin/ssh user#example.com')
child.sendLine('ls -al')
or whatever command you want to send. It will act like you are typing in a terminal.
In my script, I am trying to run a command using the sendLine() API that essentially dumps out a bunch of info to the command line. But there is a pagination that requires there to be another command where you have to press a key to continue to get to the next command.
So for example:
[Some info]
--------------- To continue, press any key. To quit, press 'q'. ---------------
[Some more info]
Is there a way that I can turn pagination off or a command I can send before I try to dump the info to the command line to turn it off?
In Linux:
You can use redirection to skip the pager(more or less). If it is important to display the output on screen, the output can be redirected to tee.
For example in man ls; ls, the man command expects the user to press q for termination and then ls is executed. To execute both the commands simultaneously without user intervention, it can be done as man ls | tee; ls. If displaying the output is not mandatory, it can be redirected to /dev/null as well.
For additional help, please specify the exact command that you are trying to execute on the remote server.
In Python: When using pexpect, the user activity can be automated if the intermediate output is known in advance. You can use expect function to wait for a particular output and then take necessary action(for example using sendLine).

How to show full output on linux shell?

I have a program that runs and shows a GUI window. It also prints a lot of things on the shell. I need to view the first thing printed and the last thing printed. the problem is that when the program terminates, if I scroll to the top of the window, the stuff printed when it began is removed. So stuff printed during the program is now at the top. So that means I can't view the first thing printed.
Also I tried doing > out.txt, but the problem is that the file only gets closed and readable when I manually close the GUI window. If it gets outed to a file, nothing gets printed on the screen and I have no way to know if the program finished. I can't modify any of the code too.
Is there a way I can see the whole list of text printed on the shell?
Thanks
You can just use tee command to get output/error in a file as well on terminal:
your-command |& tee out.log
Though just keep in mind that this output is line buffered by default (4k in size).
When the output of a program goes to your terminal window, the program generally flushes its output after each newline. This is why you see the output interactively.
When you redirect the output of the program to out.txt, it only flushes its output when its internal buffer is full, which is probably after every 8KiB of output. This is why you don't see anything in the file right away, and you don't see the last things printed by the program until it exits (and flushes its last, partially-full buffer).
You can trick a program into thinking it's sending its output to a terminal using the script command:
script -q -f -c myprogram out.txt
This script command runs myprogram connected to a newly-allocated “pseudo-terminal” (or pty for short). This tricks myprogram into thinking it's talking to a terminal, so it flushes its output on every newline. The script command copies myprogram's output to your terminal window and to the file out.txt.
Note that script will write a header line to out.txt. I can't find a way to disable that on my test Linux system.
In the example above, I assumed your program takes no arguments. If it does, you either need to put the program and arguments in quotes:
script -q -f -c 'myprogram arg1 arg2 arg3' out.txt
Or put the program command line in a shell script and pass that shell script to the script command.

Shell script : how to output to command line?

I'm making a shell script and I want to know if it's possible to write directly to the command line when the script is executed ?
Example :
user#localhost:/home/user$./script.sh
... output
... another output
... another output
... last output
user#localhost:/home/user$I want to write here on the command line
I don't want to "echo" some text, I want to write directly at the prompt.
Thanks!
No, you can't do that. If you want user to invoke your provided command after your script is finished - why not just prompt user for confirmation?
If you just want the text to show up there, but not be able to do anything with it, you can do this.
File test.sh:
echo "Output"
./test2.sh &
File test2.sh:
echo "Output2"
Notice how the first script calls the second script with the & at the end.
In this case, "Output2" will be written to the prompt, but it can't be deleted and will have no effect on the next command at all. But if this is something you're doing to grab the user's attention, it would work.
In ksh:
print -s $(script)
will print to the command history. Wrap this in a function and you'll have something close to what you are asking for.
If you are using X environment install xclip and xdotool, then:
#!/bin/bash
your scripts....
echo -n your command to write 2>&1|xclip
xdotool click 2

Resources