If you keep your local ip
executable called ip
, and not something longer, you can avoid this particular problem. If you rename it to some other one or two character long name, that will also work fine--the problem only happens if its name is three or more characters in length. This may seem strange... so read on for details...
When I run a copy of /bin/ip
called eip
, I get an error message with p
(rather than ip
) as the unknown object:
Object "p" is unknown, try "ip help".
I'm wondering if the same is happening to you? (Could there be a typo in your question?) Even if not, I strongly suspect the behavior on your machine is related to what I am seeing.
I found that when I renamed ip
to anything longer than two characters, it gave me an "unknown object" error about the rest of the characters:
ek@Io:~$ cp /bin/ip abc
ek@Io:~$ ./abc
Object "c" is unknown, try "ip help".
ek@Io:~$ mv abc foobar
ek@Io:~$ ./foobar
Object "obar" is unknown, try "ip help".
ek@Io:~$ mv foobar 12345
ek@Io:~$ ./12345
Object "345" is unknown, try "ip help".
man ip
didn't seem to explain this odd behavior, but I did notice that the first non-option argument to ip
is technically called an object:
SYNOPSIS
ip [ OPTIONS ] OBJECT { COMMAND | help }
ip [ -force ] -batch filename
OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |
tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |
netns | l2tp | tcp_metrics }
....
So I tried changing the characters, after the first two, to these object names:
ek@Io:~$ mv 12345 12addr
ek@Io:~$ ./12addr
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
....
ek@Io:~$ mv 12addr XXrule
ek@Io:~$ ./XXrule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
ek@Io:~$ mv XXrule ipl2tp
ek@Io:~$ ./ipl2tp
Usage: ip l2tp add tunnel
remote ADDR local ADDR
....
So it appears ip
is designed to check the name with which it has been invoked, and if it contains more than two characters, to interpret the remaining characters as the name of the object on which to operate. Probably this is so that copies and symbolic links of ip
with names like iplink
, ipaddr
, ipaddrlabel
, and so forth, can act as if ip link
, ip addr
, ip addrlabel
, and so on correspondingly were run.
To double check this, I took at look at the source code. The iproute2
package provides /bin/ip
, so I searched for that and found it to be provided by the source package of the same name. (This is often but not always the case.) In the code tab, I selected a branch and browsed the code, entering the ip
directory and examining ip.c
.
I looked in the main
function, since that's where most C programs start running. This is the function that begins:
int main(int argc, char **argv)
{
Like many programs' main
functions, it consists largely of processing for command-line options. But below that, there's code to handle the various ways ip
may be run, and one of them is for when its name is more than two characters long:
if (strlen(basename) > 2)
return do_cmd(basename+2, argc, argv);
Cool! (Kinda weird--but cool.)
The simplest and best solution is probably just to keep your copy of ip
called ip
, or some other one- or two-character name. Giving it the same name as the copy of ip
in /bin
(and pointed to by the /sbin/ip
symlink) should not be a problem--your script is already providing a path to the specific executable you wish to run.
However, you might want it to be possible for users to invoke your copy of ip
with a command like eip
--for example, so they can have a separate command to put in directories in their PATH
. This is commonly achieved with a symbolic link, but that will fail here for the same reason calling the copy eip
failed in the first place:
ek@Io:~$ ln -s /bin/ip eip
ek@Io:~$ ./eip
Object "p" is unknown, try "ip help".
(I made a symbolic link to my system's /bin/ip
, but the same happens when you symlink to a separate copy.)
The solution is to write a wrapper script (named eip
, or whatever you like) that invokes ip
, passing its arguments along. The script file can look like this:
#!/bin/sh
/path/to/your/ip "$@"
Best Answer
Instead of the symbolic link you can create a wrapper script in /usr/local/bin:
Make the script executable with
chmod +x /usr/local/bin/octane
.The "$@" are the command line arguments, so you can still run
octane an_argument
.The script changes the CWD (current working directory) only inside the script, because the script is run in a whole new shell instance which ends at the end of the script. Changing the current working directory for the executable might actually be a problem if you want to give a relative pathname to the executable. E.g. if you are in your home directory and run
octane a_file_in_the_home_directory
, it doesn't work, because the octane executable is called with a CWD of /opt/octane, and a_file_in_the_home_directory is not in /opt/octane. If that is a concern, you can either remember to give absolute pathnames only (octane ~/a_file_in_the_home_directory
) or use a more complicated version of the script.