Find and kill specific processes in bash - bash

I'm looking for a way to find and kill specific processes in bash, for example, say I have a script that opens a text file, and this is in a loop opening the text file over and over again, so the same text file is overlapping itself, how would I go about closing the previous text file before the next one can open? I've found several ways on here explaining how to kill specific processes by name or PID, but none of them give me what I'm looking for, and I'm unable to get a lot of the answers offered to work, have spent a while trying to figure out this small issue, just wondering if anyone can offer anything. Thanks.

Opening and closing files, as you are doing, is handled by the various programs that you run. Bash does not have separate operations to open and close files explicitly, only ways to read and write them. You can kill a process to ensure that it can't do anything further with a file, but you'll have to be more specific if that is not what you're after.

Related

Monitor A File For Additions And Get Last Added Line

I'm having trouble monitoring a file for changes. I need to be able to know when a file changes, and when it does, I need the new line that was added. I intend to parse each line and find ones that match certain criteria, and act on information in those lines. I know the expected number of matching lines ahead of time, but I do not know how many lines in total will be added to the file, or where the matching lines will be.
I've tried 2 packages so far, with no avail.
fsnotify/fsnotify
As fas as I can tell, fsnotify can only tell me when a file is modified, not what the details of the modification was. Since I need to know what exactly was added to the file, this is no good for me.
(As a side-question, can this be run in a loop? The example that I tried exited after just one modification. I need to monitor for multiple modifications.)
hpcloud/tail
This package tries to mimic the Unix tail command, but it seems to have its own issues. The output that I get includes timestamps and other data - I just want the added line, nothing else. Also, it seems to think a file has been modified multiple times, even when it's just one edit. Further, the deal breaker here is that it does not output the last line if the line was not followed by a newline character.
Delegating to tail
I came across this answer, which suggests to delegate this work to the tail command itself, but I need this to work cross-platform (specifically, macOS, Linux and Windows). I don't believe that an equivalent command exists on Windows.
How do I go about tackling this?
#user2515526,
Usually changed diff is out of scope of file watchers' functionality, because, you know, you could change an image, and a watcher would need to keep a track several Mb of a diff in memory, and what if we have thousands of files?
However, as bad as it sounds, this may be exactly the way you want to implement this (sure, depends on your app, etc. - could be fine for text files), i.e. - keeping a map of diffs (1 diff per file) since last modification. Cannot say I like it, but sounds like fsnotify has no support for changes/diffs that you need.
Also, regarding your question about running in a loop, maybe you can get some hints here: https://github.com/kataras/iris/blob/8370d76910cdd8de043753ed81ae080eae8dc798/utils/file.go
Its a framework that allows to build a server that watches for TypeScript file changes. So sounds similar to your case/question.
Cheers,
-D

Closing all pipes of a process

I am working on making a program that will act in a similar way as a shell, but supports only foreground processes and pipes. I have multiple processes writing to the same pipe and some other properties that differ from the normal usage of pipes. Anyhow, my question is,
Is there any easy (automatic) way to close all file descriptors of a process except the three basic ones?
I am asking this question since I have a lot of difficulties keeping track of all file descriptors for every process. And sometimes they act in some unpredictable ways to me. It could be also because of the fact that I don't have a very thorough understanding of them.
Is there any easy way(automatic) to close all file descriptors of a process except the three basic ones?
The normal way to do this is to simply iterate over all of them and close them:
for (i = getdtablesize(); i > 3;) close(--i);
That's already a one-liner. It doesn't get any more "automatic" than that.
I am asking this question since I have a lot of difficulty keeping track of all file descriptors for every process.
It will be worth your time to think about the life cycle of each file descriptor you open, when it gets duplicated (e.g. dup2() and fork()), how it gets used, and make sure you account for how each one is going to get closed when it is no longer needed. Papering over a problem of leaked file descriptors by indiscriminately closing them all is not going to be sustainable.
I have multiple processes writing to the same pipe
If you do this, then you need to be aware that the order in which data arrive at the other end of the pipe is going to be unpredictable. It will be difficult to avoid corrupting the data stream.
Use the closefrom(3) C library function.
From the manpage:
The closefrom() system call deletes all open file descriptors greater
than or equal to lowfd from the per-process object reference table.
Any errors encountered while closing file descriptors are ignored.
Example usage:
#include <unistd.h>
int main() {
// Close everything except stdin, stdout and stderr
closefrom(3); // Were 3 is the lowest file descriptor you wish to close
printf("Clear of all, but the three basic file descriptors!\n");
return 0;
}
This works in most unices, but requires the libbsd support library for Linux.

gVim startup message & info suppression

I got a partial answer to my problem before, and want to solve this problem fully now. The final line of my /Program Files/GNU/vim/_vimrc is
source /homedir/vimsession_file
The filenames that i edit do not change, only their content changes. But, once in a while, i would create a new session file before i exit vim, using
:mks! /homedir/vimsession_file
Everytime i start gVim, i get a message box listing all the files (which I load into the multiple tabs that i have) with a Line number and Character count listed. More detail of this can be found in my orignal post here.
Currently, i am not using the solution proposed in the link given above. The solution i got there was to replace the final line of /Program Files/GNU/vim/_vimrc with the following line:
autocmd VimEnter * source /homedir/vimsession_file
The reason I stopped using the above solution is because my buffers were all getting wiped out (as described in the original post link). So, i was forced to rebuild my buffers every once in a while, when i would restart gVim.
I did search and read in order to solve this on my own. But the closest solution that i saw was here in stackoverflow. But that solution did not work for me either, despite playing with the shortmess variable as suggested there. How can i stop this annoying message box that pops up with OK button, before the start of gVim ? I want to suppress the message box, because the only info i get from it are the line and character count for each file. (NOTE: I looked into the /homedir/vimsession_file and it is about 3500 lines long. I noticed that the file names occur with badd followed by the edit command. For example, i have line 96 and line 164 as below:
Line 96 : badd +16 \Program\ Files\GNU\vim\_vimrc
........
Line 164: edit \Program\ Files\GNU\vim\_vimrc
This pattern repeats for all the other files that get loaded into multiple windows/tabs.
Wanted to post the answer here because there seem to be very few VIM experts who regularly look at stackoverflow. I didn't have the patience to wait many days expecting an answer. I found the answer to my own question, after reading the help file in vim called "starting.txt" which explains the startup/init process of vim and the different initialization files used. The following steps removed the annoying pop-up message box for me, and also made my VIM process start much faster than before due to simplification.
According to what is suggested in starting.txt help file, I separated my numerous tabs/windows/files into different sessions. I recommend reading through this help file (atleast browsing it), if you are a regular user of VIM.
Previously i was lumping numerous files (from different projects) into one single vim session. This is messy and is not the recommended way to use a VIM session file. Before the creation of different session files (for different projects), i first saved my old vim session file so that i can reuse it, during the creation of different session files. You will understand the process clearly if you look at the help file.
I cleaned up my startup procedure further by setting up a new viminfo file, by adding the "-i" parameter to vim.exe (icon) for starting. This was pointed to a new directory and hence gave a fresh start.
The main init files used by vim are viminfo, vimrc and session file. Each is meant for a different purpose. My problem was caused by source /homedir/vimsession_file as the final line of in my vimrc. So, I removed that line, and instead issue that command manually now, after vim starts up (with an empty window). I can source different vimsession_files, in order to load different files (which belong together). On my machine this command takes about 1 second, to load many tabs/windows/files, which belong to a single project/sub-project.
As pointed in the original post URL given in my question, there maybe another way to resolve this by creating and looking at the vimlog file. But i didn't want to bother with that tedious process. The way i am setup now makes more sense to me, because I have various subprojects which properly belong in different sessions of VIM.

Adding commands in shell scripts to history?

I notice that the commands I have in my shell scripts never get added to the history list. Understandably, most people wouldn't want it to be, but for someone who does, is there a way to do it?
Thanks.
Edit:
Sorry about the extremely late reply.
I have a script that conveniently combines some statements that ultimately result in lynx opening a document. That document is in a dir several directories below the current one.
Now, I usually end up closing lynx to open another document in the current dir and need to keep switching back and forth between the two. I could do this by having another window open, but since I'm mostly on telnet, and the switches aren't too frequent, I don't want to do that.
So, in order to get back to lynx from the other document, I end up having to re-type the lynx command, with the (long) path/filename. In this case, of course, lynx isn't stored in the command history.
This is what I want added to the history, so that I can get back to it easily.
Call it laziness, but hey, if it teaches me a new command....
Cheers.
As #tripleee pointed out, which problem are you actually trying to solve? It's perfectly possible to include any shell code in the history, but above some level of complexity it's much better to keep them in separate shell scripts.
If you want to keep multi-line commands in the history as they are, you might want to try out shopt -s lithist, but that means searching through history will only return one line at a time.

2-way communication with background process (I/O)

I have a program that runs in the command line (i.e. $ run program starts up a prompt) that runs mathematical calculations. It has it's own prompt that takes in text input and responds back through standard-out/error (or creates a separate x-window if needed, but this can be disabled). Sometimes I would like to send it small input, and other times I send in a large text file filled with a series of input on each line. This program takes a lot of resources and also has a large startup time, so it would be best to only have one instance of it running at a time. I could keep open the program-prompt and supply the input this way, or I can send the process with an exit command (to leave prompt) which just prints the output. The problem with sending the request with an exit command is that the program must startup each time (slow ...). Furthermore, the output of this program is sometimes cryptic and it would be helpful to filter the output in some way (eg. simplify output, apply ANSI colors, etc).
This all makes me want to put some 2-way IO filter (or is that "pipe"? or "wrapper"?) around the program so that the program can run in the background as single process. I would then communicate with it without having to restart. I would also like to have this all while filtering the output to be more user friendly. I have been looking all over for ideas and I am stumped at how to accomplish this in some simple shell accessible manor.
Some things I have tried were redirecting stdin and stdout to files, but the program hangs (doesn't quit) and only reads the file once making me unable to continue communication. I think this was because the prompt is waiting for some user input after the EOF. I thought that this could be setup as a local server, but I am uncertain how to begin accomplishing that.
I would love to find some simple way to accomplish this. Additionally, if you can think of a way to perform this, do you think there is a way to also allow for attaching or detaching to the prompt by request? Any help and ideas would be greatly appreciated.
You could create two named pipes (man mkfifo) and redirect input and output:
myprog < fifoin > fifoout
Then you could open new terminal windows and do this in one:
cat > fifoin
And this in the other:
cat < fifoout
(Or use tee to save the input/output as well.)
To dump a large input file into the program, use:
cat myfile > fifoin

Resources