How to use the stap -L option? - linux-kernel

I am following the SystemTap tutorial and I am trying to do exercise 1 from section 2.3 - "Tracing. Exercises". The -L option seems to never work. I got this script:
probe kernel.function("*nit*"){}
I type in a terminal:
$ stap -L PROBE t.stp
and nothing happens.

$ stap -L 'kernel.function("blahblah")'
Systemtap is great, but poor documentation.

From man stap (with systemtap*-1.7-2.fc15.x86_64 RPMs installed)
stap [ OPTIONS ] -l PROBE [ ARGUMENTS ]
stap [ OPTIONS ] -L PROBE [ ARGUMENTS ]
-l PROBE
Instead of running a probe script, just list all available probe
points matching the given single probe point. The pattern may
include wildcards and aliases, but not comma-separated multiple
probe points. The process result code will indicate failure if
there are no matches.
-L PROBE
Similar to "-l", but list probe points and script-level local
variables.
"probe points" refer to 'kernel.function("blahblah")', etc. There is no keyword "probe" before and no probe handler afterwards.

You can try the following examples.
To get a list of all Kernel functions.
$ stap -l 'kernel.function("*")' | sort
kernel.function("vfs_read#/build/linux-lts-xenial-Hu9lgy/linux-lts-xenial-4.4.0/fs/read_write.c:440")
[....]
To get a Kernel function & arguments (local variables)
$ stap -L 'kernel.function("*")' | grep vfs_read
kernel.function("vfs_read#/build/linux-lts-xenial-Hu9lgy/linux-lts-xenial-4.4.0/fs/read_write.c:440") $file:struct file* $buf:char* $count:size_t $pos:loff_t*
[....]

stap -L kernel.function("*nit*") | sort

Just to add on to what more learned people than me have said:
stap -L 'module("module-name-here").function("*")'
For regular kernel probes:
stap -L 'kernel.function("*")'
Hope this helps someone else in the future!

Related

Shell script grep command -c (count) -- does command-line ordering matter?

just a quick question regarding a doubt. What's the difference between these two:
grep "$genre" "$i" | grep "$type" -c
and
grep "$genre" "$i" | grep -c "$type"
Do they do perhaps the same thing?
The POSIX standard-mandated behavior for grep "$type" -c, presuming that $type does not expand to a string starting with a dash, is to treat -c as a filename.
Only nonstandard versions of grep (such as the one built by the GNU project and commonly found on Linux systems) will treat -c as an option enabling "count" behavior when it isn't before the first positional argument.
It's bad practice to write your scripts to require nonstandard tools unless they gain some concrete benefit from those tools. Use grep -c "$type".
As you can see from man grep, the -c switch belongs to the so-called "General Output Control". Those switches can be placed on different places in the grep ... command and this has no impact on the general outcome, so indeed, both lines you mention are equal.

Argument list too long from shell script

one case:
I wrote script on tsch that invoke other script on python.
When I invoke python script from cmd , it is OK.
When I invoke test script on tsch then I get error: Argument list too long
Another case:
git grep -e "alex" -- `git ls-files | grep -v 'bin'`
I also get error: Argument list too long.
What can problem and How to solve it ?
Updated Answer
I'm not familiar with the specific git commands you are using and you don't seem to be replying sensibly to the questions in the comments either. I guess you probably want something like this though:
git ls-files | grep -v 'bin' | xargs -L 128 git grep -e "alex" --
Original Answer
The classic way to solve "error: Argument list too long" is with xargs. It can be used to repeatedly call a script whose name you provide, or echo if you don't provide one, with a limited number of arguments till the arguments are all consumed.
So, imagine you have a million files in a directory, then ls * will fail, however a simple ls will work. So, we can put that to use with:
ls | xargs -L 128
which will call echo (because we didn't provide a utility name) repeatedly with 128 filenames at a time till all are echoed.
So, you could do:
ls | xargs -L 128 yourScript.py
to call your Python script repeatedly with 128 filenames at a time. Of course you may be doing something completely different and incompatible with this technique but your answers are not very helpful so far...
for somebody comes here who need to do something like this:
./shell_script.sh param1
but it raises error Argument list too long from shell script of param1.
I just run into this, and fix it by a workaround of using the shell variable.
# calling the PARAM1 instead of $1 in code of shell_script.sh
export PARAM1=param1 ./shell_script.sh
an example of a ruby version of transferring string to nodejs:
ENV["PARAM1"]="a_bunch_of_test_string_as_longer_as_you_can"
`node node_script.sh`
var param1 = process.env.PARAM1;
console.log(param1);

How to use nslookup in bash to verify is DNS is configured properly?

Mainly I want to detect if DNS is configured properly on a machine by using nslookup. Sadly it seems that nslookup still returns success error codes when it fails to lookup an entry. Also the fact that different queries could return multiple results makes it harder to test it.
So I want to write a bash snippet that returns success if the dns entry resolved successfully. I don't care if I get multiple results.
Example nslookup -type=srv _ldap._tcp.DOMAIN.COM
The correct solution would be to use dig and test if there is any text with the short option:
[ "$(dig +short -t srv _ldap._tcp.example.com.)" ] && echo "got answer"
Agree the fact, nslookup, returns 0 for both successful and failing DNS look-ups. You can achieve what you are trying to do, but post-processing the output of the command.
You can put up a dnsLookup.sh script with something like
#!/bin/bash
# Checking for the resolved IP address from the end of the command output. Refer
# the normal command output of nslookup to understand why.
resolvedIP=$(nslookup "$1" | awk -F':' '/^Address: / { matched = 1 } matched { print $2}' | xargs)
# Deciding the lookup status by checking the variable has a valid IP string
[[ -z "$resolvedIP" ]] && echo "$1" lookup failure || echo "$1" resolved to "$resolvedIP"
Running for some sample URL's
dudeOnMac:~$ ./dnsLookup.sh www.google.com
www.google.com resolved to 206.78.111.12
dudeOnMac:~$ ./dnsLookup.sh www.googlejunkaddress.com
www.googlejunkaddress.com lookup failure
The trick is to use host | grep commands instead of nslookup because this one is less verbose, making it much easier to parse with grep.
Here is a command that fails if the DNS resolution fails:
host -t srv _ldap._tcp.EXAMPLE.COM | grep "has SRV record" >/dev/null || {
echo "FATAL: Unable to locate ldap servers, probably you are not on intranet or your DNS servers are broken."
exit 2
}
Note: As you can see my example it specific to SRV queries but you can easily adapt change the parameter and the grep filter to make it work with others.

The -q option of bsdtar

I ran across the following code in a bash script.
# See if bsdtar can recognize the file
if bsdtar -tf "$file" -q '*' &>/dev/null; then
cmd="bsdtar"
else
continue
what did the '-q' option mean? I did not find any information in the help message of bsdtar command.
Thank you!
From the bsdtar man page:
-q (--fast-read)
(x and t mode only) Extract or list only the first archive entry
that matches each pattern or filename operand. Exit as soon as
each specified pattern or filename has been matched. By default,
the archive is always read to the very end, since there can be
multiple entries with the same name and, by convention, later
entries overwrite earlier entries. This option is provided as a
performance optimization.

Shell script takes a list of commands as input, tries to execute them, and fails

I am, like many non-engineers or non-mathematicians who try writing algorithms, an intuitive. My exact psychological typology makes it quite difficult for me to learn anything serious like computers or math. Generally, I prefer audio, because I can engage my imagination more effectively in the learning process.
That said, I am trying to write a shell script that will help me master Linux. To that end, I copied and pasted a list of Linux commands from the O'Reilly website's index to the book Python In a Nutshell. I doubt they'll mind, and I thank them for providing it. These are the textfile `massivelistoflinuxcommands,' not included fully below in order to save space...
OK, now comes the fun part. How do I get this script to work?
#/bin/sh
read -d 'massivelistoflinuxcommands' commands <<EOF
accept
bison
bzcmp
bzdiff
bzgrep
bzip2
bzless
bzmore
c++
lastb
lastlog
strace
strfile
zmore
znew
EOF
for i in $commands
do
$i --help | less | cat > masterlinuxnow
text2wave masterlinuxnow -o ml.wav
done
It really helps when you include error messages or specific ways that something deviates from expected behavior.
However, your problem is here:
read -d 'massivelistoflinuxcommands' commands <<EOF
It should be:
read -d '' commands <<EOF
The delimiter to read causes it to stop at the first character it finds that matches the first character in the string, so it stops at "bzc" because the next character is "m" which matches the "m" at the beginning of "massive..."
Also, I have no idea what this is supposed to do:
$i --help | less | cat > masterlinuxnow
but it probably should be:
$i --help > masterlinuxnow
However, you should be able to pipe directly into text2wave and skip creating an intermediate file:
$i --help | text2wave -o ml.wav
Also, you may want to prevent each file from overwriting the previous one:
$i --help | text2wave -o ml-$i.wav
That will create files named like "ml-accept.wav" and "ml-bison.wav".
I would point out that if you're learning Linux commands, you should prioritize them by frequency of use and/or applicability to a beginner. For example, you probably won't be using bison right away`.
The first problem here is that not every command has a --help option!! In fact the very first command, accept, has no such option! A better approach might be executing man on each command since a manual page is more likely to exist for each of the commands. Thus change;
$i --help | less | cat > masterlinuxnow
to
man $i >> masterlinuxnow
note that it is essential you use the append output operator ">>" instead of the create output operator ">" in this loop. Using the create output operator will recreate the file "masterlinuxnow" on each iteration thus containing only the output of the last "man $i" processed.
you also need to worry about whether the command exists on your version of linux (many commands are not included in the standard distribution or may have different names). Thus you probably want something more like this where the -n in the head command should be replace by the number of lines you want, so if you want only the first 2 lines of the --help output you would replace -n with -2:
if [ $(which $i) ]
then
$i --help | head -n >> masterlinuxnow
fi
and instead of the read command, simply define the variable commands like so:
commands="
bison
bzcmp
bzdiff
bzgrep
bzip2
bzless
bzmore
c++
lastb
lastlog
strace
strfile
zmore
znew
"
Putting this all together, the following script works quite nicely:
commands="
bison
bzcmp
bzdiff
bzgrep
bzip2
bzless
bzmore
c++
lastb
lastlog
strace
strfile
zmore
znew
"
for i in $commands
do
if [ $(which $i) ]
then
$i --help | head -1 >> masterlinuxnow 2>/dev/null
fi
done
You're going to learn to use Linux by listening to help descriptions? I really think that's a bad idea.
Those help commands usually list every obscure option to a command, including many that you will never use-- especially as a beginner.
A guided tutorial or book would be much better. It would only present the commands and options that will be most useful. For example, that list of commands you gave has many that I don't know-- and I've been using Linux/Unix extensively for 10 years.

Resources