Debug slow bash after executing command - bash

Bash randomly hangs for a few seconds after executing a command. At that stage, Ctrl+C or anything just gets printed on the terminal.
I use tmux, so I had already opened up htop to view resource usage in a different pane. All was fine. Also, when it is hung, moving to other panes works fine, I can type anything, but it hangs up when I press Enter. All of the panes execute as soon as the first pane which was hung continues. The point being resources are not a bottleneck.
I tried to use set -x in bash to check if something is happening, but due to unpredictable hangs, I had to revert it back to keep working sanely.
I also looked up How to profile a bash shell script slow startup?, but I can't find a way in there, to find slow bash after executing a command.
Any ideas how do I debug it? I am slowly going mad.
Edit: To add more context, the hang varies from 5 seconds to a minute.
To give an example, consider this:
$ ls
<--- hangs here
// after a few seconds, it continues
file1.txt
<--- never hangs here, after executing the cmd
$
And this is just an example, nothing to do with ls. I find no correlation to any particular command by which I can reproduce this.

Related

Is there a way to send a running terminal command to the background AND change the output to pipe to a log file?

Sometimes when I run a log running terminal command, I'd like to send it to the background and start doing something else in the same shell. I can do this with Ctrl+Z and bg.
However, the annoying effect this has is that it keeps showing output of the above command intermittently. Instead, when I move the process to the background, I'd also like to change where the output goes as well.
Importantly, I'm asking how to do this for an already-running command - I know that do this from scratch I could do something like command arg1 arg2 &> ~/logs/output.log &.
I have used Reptyr for this in the past.
It does have its limitations (especially with GUIs / Curses) but has worked well for me.
https://linux.die.net/man/1/reptyr
You can either start a Screen session and use reptyr to grab your running process into the screen session. Or start a new bash session which is outputting to a file and then grab the running process with reptyr.

Blocking a bash script running with &

I may have inadvertently launched a bash script containing an infinite cycle whose exit condition may be met next century, if ever. The fact is that I launched the script, as I would do with a nohup program, with
bash [scriptname].sh &
so that (as I get it, which is most probably wrong) I can close the terminal and still keep the script running, as was my intention in developing it. The script should run calculation programmes in my absence and let me gather the results after some time.
Now I want to stop it, but nothing seems to do the trick: I killed the programmes the script had launched, I removed the input file the script was getting orders from and - last and most perfect of accomplishments - I accidentally closed the terminal trying to "exit" the script, which was still giving me error messages.
How can I check whether the script is running (as it does not appear in "top")? Is the '&' relevant? Should I just ask permission to reboot the pc, if that will work and kill everything?
Thank you.
[I put a "Hi everyone" at the beginning but the editor won't let me show it. Oh, well. It's that kind of day.]
Ok, I'll put it right here to prove my stupidity, as I wandered the internet shortly (after a long wandering before writing this post) and found that the line:
kill -9 $(pgrep -f [SCRIPTNAME].sh)
does the trick from any terminal window.
I write this answer to help anyone in the same situation, but feel free to remove the thread if unnecessary (and excuse me for disturbing).
Good you found it, here is another way if you do not use bash -c and run it in current shell not a separate shell.
# put a job in background
sleep 100 &
# save the last PID of background job
MY_PID=$!
# later
kill $MY_PID

Programmatically/script to run zsh command

As part of a bigger script I'm using print -z ls to have zsh's input buffer show the ls command. This requires me to manually press enter to actually execute the command. Is there a way to have ZSH execute the command?
To clarify, the objective is to have a command run, keep it in history, and in case another command is running it shouldn't run in parallel or something like that.
The solution I've found is:
python -c "import fcntl, sys, termios; fcntl.ioctl(sys.stdin, termios.TIOCSTI, '\n');
I'm not sure why, but sometimes you might need to repeat the command 2 times for the actual command to be executed. In my case this is happening because I send a process to the background, although this still doesn't make much sense because that process is sending a signal back to the original shell (triggering a trap) which actually calls this code.
In case anyone is interested, this was my goal:
https://gist.github.com/alexmipego/89c59a5e3abe34faeaee0b07b23b56eb

How can I prevent I/O redirection from silently failing upon modifying the file elsewhere?

I'm trying to write a simple shell script to start a program running in the background and redirect all its output to a log file, but I've come across a case where it silently fails and kills the program.
It happens if the file that's being redirected into is modified elsewhere. I've tried recreating the situation using the ping command so I can narrow the problem down to not being my program's code, but that fails in a different way - it stops writing to the file, but the terminal still acts as though the ping is running.
This is the essence of my code:
sh "$program" > "$file"

Is there a way for a backgrounded task to inform the terminal to print a new prompt?

I want to write a program that can be run as a backgrounded task (i.e. my-thing &), and that will beautifully provide relevant output when necessary.
However, with background tasks that print to the terminal, there's always this annoying little progression:
bash-3.2$ my-thing &▏
bash-3.2$ my-thing &
bash-3.2$ -- Hello from my-thing!
-- now let me start doing what I do best ...
▏
… notice that we now have no prompt before the cursor, not to mention that there's an ugly erraneous prompt where my program spat out output while a prompt had already been printed.
Thus, I want three things, only one of which I don't have any idea how to go about doing:
Detect whether my program is being run in the background, and alter my output/operation accordingly (i.e. print out less useless information; queue further information to only be output when the program is foregrounded again; etceteras)
Clear out the prompt (if it already exists) when suddenly printing information to a terminal we've been backgrounded in
Inform the terminal after I've finished whatever I'm printing to the terminal for, somehow forcing it to re-draw a new prompt below the content I've added
The third is the only one I have absolutely no idea how to go about; though I've got some inklings on the other two, any links or suggestions there would be appreciated as well.
Equally appreciated, even, would be links to any programs (any language/environment) which already have modes that operate this; as I could attempt to reverse-engineer/spelunk their implementation.
This works for me:
echo 'sleep 1; echo; echo hi' > /tmp/hi
chmod +x /tmp/hi
zsh
/tmp/hi &
asdfsadf # type whatever, here.
After the 'hi' gets echo'd, zsh knows to redraw your prompt with the 'asdfasdf' intact.
So, no big surprise: zsh being better than bash.

Resources