i have a hello world C example ./a.out
Now i measured execution time using time for below commands
time ./a.out
Hello World
real 0m0.001s
user 0m0.000s
sys 0m0.002s
time runuser -l root -c './a.out'
real 0m0.017s
user 0m0.004s
sys 0m0.011s
time su -s /bin/bash -c "./a.out" root
Hello World
real 0m0.080s ---> 80 times slower
user 0m0.005s
sys 0m0.071s
Why is the third command 80 times slower than the first command?
Environment -- Redhat 7
With the second and third command, the time command also times the launch of runuser, su and bash, which takes some time as well.
It shouldn't make so many difference if you do:
$ runuser -l root -c 'time ./a.out'
and:
$ su -s /bin/bash -c "time ./a.out" root
Related
I have this simple hello world program:
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
I compiled this program with LLVM Clang (v15.0.1, built from Homebrew, so not Apple's version) like normal, then I ran and timed the outputs. To my surprise, the first time the program ran, it took nearly 10x longer than the second time, but the next three executions run much faster.
$ clang test.c -o test
$ time ./test
Hello, world!
real 0m0.169s
user 0m0.001s
sys 0m0.002s
$ time ./test
Hello, world!
real 0m0.017s
user 0m0.001s
sys 0m0.006s
$ time ./test
Hello, world!
real 0m0.004s
user 0m0.001s
sys 0m0.002s
$ time ./test
Hello, world!
real 0m0.008s
user 0m0.001s
sys 0m0.005s
I'm running this on an Intel Core i5 mac, running macOS Big Sur v11.6.8. The shell is the bash shipped with macOS.
Nothing in my code deals with time, and I don't think there's anything to cache, so I'm not sure why the first execution runs so slow. I suspect that the OS might be doing some kind of optimization, but I don't know what/how. What is the cause of this large discrepancy in runtimes?
When compiling multiple files with gcc (i.e: gcc *.c), a large project may take some time to compile and, if no errors are found, the screen remains static for some time. Does gcc have a command line option to display the filename of the c file its currently compiling?
gcc is just a driver program which uses cc1 to actually compile input C files.
That said, you can simply check arguments of gcc child processes to get what gcc is up to. I.e:
> gcc 1.c 2.c & ps -f --forest
[1] 22907
UID PID PPID C STIME TTY TIME CMD
myaut 21963 18153 0 20:21 pts/1 00:00:00 /bin/bash
myaut 22907 21963 0 20:41 pts/1 00:00:00 \_ gcc 1.c 2.c
myaut 22909 22907 0 20:41 pts/1 00:00:00 | \_
/usr/lib64/gcc/x86_64-suse-linux/4.8/cc1 -quiet 1.c -quiet -dumpbase
1.c -mtune=generic -march=x86-64 -auxbase 1 -o
myaut 22908 21963 0 20:41 pts/1 00:00:00 \_ ps -f --forest
In this example I was lucky enough to capture child process which actually compiles 1.c with ps which has started almost simultaneously with gcc
Anyway, using a full fledged building system on top of GCC (make, CMake or SCons) is a much better for compiling project consisting of multiple files.
I am using Ubuntu 16.10.
I was following along a book, doing something like this:
#include <stdio.h>
int main() {
printf("Real UID:\t%d\n", getuid());
printf("Effective UID:\t%d\n", geteuid());
}
And to run this file as sudo without using the sudo command, after compiling with gcc, I changed the owner and group to root.
$ gcc -o test test.c
$ sudo chown root:root ./test
$ chmod u+s ./test
$ ls -l
-rwsr-xr-x 1 root root 8512 Mar 9 test
Now, this is what I got when I executed the file. My UID is 1000.
$ ./test
Real UID: 1000
Effective UID: 1000
The book I was reading said the result should be like this:
$ ./test
Real UID: 1000
Effective UID: 0
The UID for root is 0, right? Does this mean that I am running an -rwsr-xr-x file, owned by root, with my own user privilege? I don't understand.
Is your book a little on the older side? It seems like modern *nix variants widely ignore the sticky bit on executable files:
[...] the Linux kernel ignores the sticky bit on files. [...] When the sticky bit is set on a directory, files in that directory may only be unlinked or renamed by root or the directory owner or the file owner.[4]
https://en.wikipedia.org/wiki/Sticky_bit
Here is my current makefile, which does not run test correctly:
shell2: shell2.o
shell2.o: shell2.c
clean:
rm -f *.o
test: shell2
./shell2
pwd
./shell2
cd ..
./shell2
jobs
./shell2
sleep 100 &
jobs
./shell2
exit
My program tests for newline to know when a command has been entered. This is the output of my
program when I compile it myself manually:
$ pwd
/students/8/[redacted]/[redacted]/Shell2
$ cd ..
$ jobs
Jobs:
$ sleep 1000 &
To the background: 20203
$ jobs
Jobs:
20203
$ jobs
Jobs:
20203
$ killall sleep
sleep(17014): Operation not permitted
sleep(17305): Operation not permitted
sleep(17433): Operation not permitted
sleep(19741): Operation not permitted
sleep(19841): Operation not permitted
sleep(20041): Operation not permitted
sleep(20183): Operation not permitted
$ jobs
Jobs:
$ exit
now exiting...
Here is the output when I run make test:
make test
./shell2
$ pwd
/students/8/[redacted]/[redacted]/Shell2
./shell2
$ cd ..
./shell2
$ jobs
make: jobs: Command not found
make: *** [test] Error 127
Also, I have to hit ctrl+D every time for a new line to execute during make test.
I'm trying to write this makefile for my class so that I can submit my assignment, my professor did not explain at all how to use a makefile besides the basic
./a.out [input command]
He never explained how to use a makefile in the case that your program is running on a continuous loop like a shell is, waiting for the user to press [enter] or new line for the command to be parsed.
I checked the GNU man for make but it didn't explain much in the "testing" section.
Thanks for your help, I really appreciate it.
test_input.txt's output:
./shell2 < test_input.txt
"Sending command: pwd"
/students/8/[redacted]/[redacted]/Shell2
"Sending command: cd .."
"Sending command: pwd"
/students/8/[redacted]/[redacted]
"Sending command: jobs"
$ $ $ $ $ $ $ $ Jobs:
$
"Sending command: sleep 1000 &"
$ $ To the background: 27199
"jobs"
$ $ Jobs:
27199
$
"Sending command: killall sleep"
$ $ $ $ Jobs:
"Sending command: jobs"
$ $ now exiting...
"exit"
test_input.txt:
echo "Sending command: pwd"
pwd
echo "Sending command: cd .."
cd ..
echo "Sending command: pwd"
pwd
echo "Sending command: jobs"
jobs
echo "Sending command: sleep 1000 &"
sleep 1000 &
echo "jobs"
jobs
echo "Sending command: killall sleep"
killall sleep
echo "Sending command: jobs"
jobs
echo "exit"
exit
It looks like you're trying to supply input to your program. You can't do this with make (directly) as make simply executes each line with /bin/sh -c COMMAND.
What you can do is
test: shell2
./shell2 < test_input.txt
to redirect input to the file test_input.txt, which would contain the commands you want.
For some reason one of my directories has started producing
executables. By this I mean that new files in that directory are
a+x (but not, for example in the parent directory):
$ ls -ld .
drwxrwsr-x 2 me me 45 Dec 5 10:22 ./
drwxrwsr-x 10 me me 13 Dec 5 10:22 ../
$ rm -f test
$ touch test
$ ls -l test
-rwxrwxr-x 1 me me 0 Dec 5 10:25 test*
$ cd ..
$ rm -f test
$ touch test
$ ls -l test
-rw-rw-r--+ 1 me me 0 Dec 5 10:26 test
Also, notice the + at the end of the second permissions line, is it significant?
I know it cannot be a umask thing...but it's set at 0002.
How can I turn off this behavior?
EDIT:
In response to an answer below I ran the following (in the parent dir):
$ touch test
$ getfacl test
# file: test
# owner: me
# group: me
user::rw-
group::rw-
mask::rwx
other::r--
Why do I have this mask? Is this the right value for it? How can I change it?
The + indicates the presence of one or more ACLs on the entry. getfacl test will show you more information. The oddity with the apparent executability of new files may be related to the ACLs in the parent directory, but we'd have to see what they are to know for sure...