4 ms·
It should be noted that you shouldn't really do > $ strace uptime 2>&1 | grep open Instead, you should do `strace -e open uptime` to select that system call.
by herpderperator 7y ago
It should be noted that you shouldn't really do
> $ strace uptime 2>&1 | grep open
Instead, you should do `strace -e open uptime` to select that system call. Like Useless Use of Cat[0], this could be considered a Useless Use of Grep.
[0] https://en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat https://en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_...
Edit: Heh, when I went back to continue reading the article this was mentioned on the following line. Oops :)
- CUViper 7y agoYou might need to cover openat too. I think newer glibc uses the openat(AT_FDCWD,...) syscall for all open calls.
- jimmaswell 7y agoIf the cat or grep makes the command more clear or easier to write then it's not useless.
- rndgermandude 7y agoAgreed, but you should also keep in mind that this means extra work. Often the difference is negligible. But if you e.g. strace a syscall-wise very busy process and pipe that into grep, all the logging strace does that is then piped over to grep just to be discarded by grep eventually, may actually affect performance a lot; while strace -e avoids this extra work.
- AdrienLemaire 7y agoI tried both, but the `-e open` option doesn't return anything $ strace uptime 2>&1 | grep open openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/proc/uptime", O_RDONLY) = 3 ... $ strace -e open uptime 10:12:14 up 2 days, 18:52, 1 user, load average: 1.22, 1.30, 1.71 +++ exited with 0 +++ $ strace -- version 5.3 Optional features enabled: stack-trace=libunwind stack-demangle m32-mpers mx32-mpers After digging in the documentation, I finally found something working: $ strace -e trace=openat uptime EDIT: got it. my system calls are openat, not open. Hence the following works $ strace -e openat uptime
- ddevault 7y agoI disagree in this case, I think it's more Unix-style to use grep when appropriate. You should learn a lot of generally applicable tools, not the intricate details of a few specialized tools. The "useless cat" case can be represented as, instead of grep foo filename, grep foo < filename.
- herpderperator 7y agoThat's like saying you can just use `find . | grep ... | wc -l` and then learning the hard way that you can have newlines in filenames. While I agree you should learn lots of general tools, you should not stop there. If you have a particular need you should consult the manpage; it is one of the ways you become better. In the htop example it might be fine as a quick-and-dirty method, but when teaching others like through this particular blog post you should do so the right way.
- lixtra 7y agoIf your pipeline is meant to count files then the bigger problem is that it counts directories too. If you have filenames with newlines you may have other - less nasty - stuff too. So you either get a reasonable answer in 1s (or 2s if you have short look at the output before counting). Or you spend 1h+ discussing requirements and carefully writing a program that gives a precise answer. Things to consider: - how to treat symlinks - how to treat hardlinks - what if files are added/removed to/from the directory tree while you scan - how to react to missing read permissions - is your regex on the whole path or just on the basename - ...
- herpderperator 7y agoWell, in Unix, everything is a file[0], even directories. So when I mentioned filenames, this includes directories. :-) As a real-world example for those who are curious, running mkdir twice yields errno 17, EEXIST, which is "File exists"[1]: root@vbox:~# mkdir directory root@vbox:~# mkdir directory mkdir: cannot create directory ‘directory’: File exists But sure, the fast way could be mostly right, and maybe your goal is to just get it done and not get better at these tools, in which case, sure. [0] https://en.wikipedia.org/wiki/Everything_is_a_file https://en.wikipedia.org/wiki/Everything_is_a_file [1] https://elixir.bootlin.com/linux/latest/source/include/uapi/asm-generic/errno-base.h#L21 https://elixir.bootlin.com/linux/latest/source/include/uapi/...
- jrockway 7y agoThese are two different commands. "strace | grep foo" looks for any line containing foo. It will find "foobar" and "food" system calls. It will find the word "foo" in the (abridged) string data that it prints out (read(..., "foo...", ...)). Meanwhile, strace's -e filter will find exact matches of syscalls that are named on the command line. Obviously the author wants the second one, but it is hardly useless to grep. And, once you know how to use grep, you know how to do this sort of search for every program ever written. It is nice that strace has its own budget string matching built in... but knowing how strace works only tells you how strace works. Knowing how grep works lets you do this sort of thing to any program that outputs text. (A lot of work has been done to try and make something as good as "strace -e" but generically; for example, Powershell's Select-Object cmdlet. I have never managed to get that to do anything useful, but they did manage to break grep, erm ... Select-String, in the process. Great work!)
- herpderperator 7y agoAs I have mentioned in another reply, just because you know grep does not mean you should stop there. Especially when teaching others, you should find the optimal way and mention that you _could_ also use grep if you were in a rush. You could always do things the quick-and-dirty way, but does that help you grow as a programmer? You could write Python code that looks like C, like many people do when they come from a C background, or you could learn how to write Pythonic code by reading the documentation and examples. > Knowing how grep works lets you do this sort of thing to any program that outputs text. It's worth noting that I could say the same about strace. Once you know strace, you could run it against any program that uses system calls, which by the way, is many. :-)