Determine command line arguments a program uses to launch another one? - linux

Motivation: When I run grub-mkrescue, it internally launches xorriso to write an iso file. I want to see what command line arguments xorriso is being passed. I know I could check the sources of grub-mkrescue, but I'm interested in a generic solution now. I tried with strace but the output didn't tell.
strace grub-mkrescue -o foo.iso iso/
Is there a way to do this?

A process will fork before running execve, so it will not show up in the strace of the parent.
Use strace -f to also follow children.

You can replace xorriso with a more verbose one:
which xorisso
cd $(dirname $(which ps))
mv xorisso xorisso.org
test -f xorisso | echo "mv failed, stop here"
cat <<'#' > xorisso
echo "$0 $#" > /tmp/xorisso_call.tmp
"$0.org" "$#"
#
chmod +x xorisso

Related

bash -- execute command on file change; doubling issue + how to skip loop until command completes

I'm a bash noob, and I am trying to set up a sort of "hot reload" functionality for a project I'm working on using inotifywait. Ubuntu 20.04 if that matters.
Here is what I hoped would have worked:
inotifywait -m -r ../.. -e modify,create,delete |
while read line; do
custom_command
done
I'm having two problems:
Issue #1 is that custom_command takes some time to work, and so if I make more changes to the directory in the meantime, custom command appears to "queue up" custom_command, where really I just want it to keep the most recent one and drop the others.
Issue #2 is that I'm getting some sort of "double output." So for example if I bash auto-exec.sh and auto-exec.sh looks like this:
inotifywait -m -r . -q -e modify,create,delete
Then each time a change registers, I get this as output (not a mistake that it's doubled -- I get two identical lines each time there is a modification):
./ MODIFY auto-exec-testfile.txt
./ MODIFY auto-exec-testfile.txt
I should note I've tried making changes both with Visual Code Studio and gedit, with the same results.
If I modify the bash file like so:
inotifywait -m -r . -q -e modify,create,delete |
while read line; do
echo "$line"
echo "..."
done
I get the following output each time there is a change:
./ MODIFY auto-exec-testfile.txt
...
./ MODIFY auto-exec-testfile.txt
...
If I modify bash_test.sh to the following:
inotifywait -m -r . -q -e modify,create,delete |
while read line; do
echo "help me..."
done
Then I get the following each time a change is made:
help me...
help me...
What happened to the the ./ MODIFY ... line?? Presumably there's something I don't understand about bash, stdout or similar /related concepts here?
And finally, if I change the .sh file to the following:
inotifywait -m -r . -q -q -e modify,create,delete |
while read _; do
echo "help me..."
done
Then I get no output at all. This one I think I understand, because the -q -q means that inotifywait is in "super silent" mode, so there is no log and therefore nothing to trigger the while.
What I'd love to do is just trigger the code once when something changes, and drop all but the most recent execution. I'm not sure doing this using a while is entirely necessary, but I tried inotifywait -m -r . -q -q -e modify,create,delete | echo "help me..", and the script printed "help me..." once at startup, then exited on modification.
Assistance very much appreciated.
EDIT - 20201-Mar-23
I removed -m and create from the inotifywait line, and it appears to work as expected, except that it doesn't stay "up" in monitor mode. So this at least only gives me one entry from inotifywait:
notifywait -r .. -q -e modify,delete |
while read line1; do
echo ${line1}
done
Related:
inotifywait - pause monitoring while executing command
https://unix.stackexchange.com/questions/140679/using-inotify-to-monitor-a-directory-but-not-working-100
inotifywait not performing the while loop in bash script
while inotifywait -e close_write,delete .; do
pkill custom_command
custom_command&
done

What kind of command is "sudo", "su", or "torify"

I know what they do. I was just wondering what kind of command are they. How can you make one using shell scripting.
For example, command like:
ignoreError ls /Home/
ignoreError mkdir /Home/
ignoreError cat
ignoreError randomcommand
Hope you get the idea
The way to do it in a shell script is with the "$#" construct.
"$#" expands to a quoted list of all of the arguments you passed to your shell script. $1 would be the command you want your shell script to run, and $2 $3 etc are the arguments to that command.
The only example I have is from cygwin. Cygwin does not have sudo, but I have this script that emulates it:
#!/usr/bin/bash
cygstart --action=runas "$#"
So when I run a command like
$ sudo ls -l
my sudo script does whatever it needs to do (cygstart --action=runas) and calls the ls command with the -l argument.
Try this script:
#!/bin/sh
"$#"
Call it, for example, run, make it runnable chmod u+x run, and try it:
$ run ls -l #or ./run ls -l
...
output of ls
...
The idea is that the script takes the parameters specified on the command line and use them as a (sub)command... Modify the script this way:
#!/bin/sh
echo "Trying to run $*"
"$#"
and you will see.

how to give input to secondary prompt which comes after running a script

$ cat messing_script.sh
#!/bin/sh
ext=`date '+%m%d%H%M'`
host=`hostname`
datalog=/export/admin/imsimta
dire=`date '+%m%d'`
datadir=$datalog/$host/$dire
if [ ! -d $datadir ]
then
mkdir -p $datadir 2> /dev/null
fi
dir1=/opt/sun/comms/messaging64/sbin/
cd $dir1
sleep 5
./imsimta qm
sleep 2
top > $datadir/$ext 2> /dev/null
exit
imsimta, if it spawns a shell, probably supports an option to run a string. Try one of:
./imsimta qm -c "top > $datadir/$ext"
or
./imsimta qm << EOF > $datadir/$ext
top
EOF
The second case is probably easier as echo top | ./imsimta qm, but the heredoc makes it easier to expand as needed. Neither of these is guaranteed to work, and they depend on how imsimta is implemented. I strongly recommend not discarding stderr until you have a working script.

How do I create a flag using getopts to run mount command in linux?

I need help with my script.
My script is to find if a mount exists. Though I want it run only if I pass a flag using getopts. How can I do that?
FS_TO_CHECK="/dev"
if cat /proc/mounts | grep $FS_TO_CHECK > /dev/null; then
# Filesystem is mounted
else
# Filesystem is not mounted
fi
The simplest example of passing a command line argument:
$ ./MyScript.sh some_parameter
MyScript.sh:
#!/bin/bash
echo $1
Here's a simple tutorial on getopts.

Redirecting the output of program which itself is an argument

Let me present the scenario first with the command which is not working under linux bash environment.
$ timed-run prog1 1>/dev/null 2>out.tmp
Here in the above case I want to redirect the output of program 'prog1' to /dev/null and out.tmp file. But this command is redirecting the output (if any) of timed-run to out.tmp.
Any help will be appreciated.
From a simple example, I experience exactly the opposite.
$ time ls 1> foo 2> bar
real 0m0.002s
user 0m0.004s
sys 0m0.000s
$ more foo
<show files>
$ more bar
<empty>
$
The output of ls is redirected, and the output of time is not!
The problem here is in timed-run not in bash. If you run the same command replacing timed-run with the standard time command this works as you expect. Mainly timed run needs to run the arguments of prog1 through the shell again. If it is a shell script you can do this with the eval command. For example:
#!/bin/sh
echo here is some output
echo $*
eval $*
now run
timed-run prog1 '1>/dev/null' '2>output.tmp'
How about using sh -c 'cmd' like so:
time -p sh -c 'ls -l xcvb 1>/dev/null 2>out.tmp'
time -p sh -c 'exec 0</dev/null 1>/dev/null 2>out.tmp; ls -l xcvb'
# in out.tmp:
# ls: xcvb: No such file or directory

Resources