0

On Ubuntu 22, using Python 3.10, I need to set up a VPN connection and analyze the response from the VPN server. I do this as follows:

connect_command = ['ip', 'netns', 'exec', 'vpn_test_namespace', 'ipsec', 'up', 'vpn_test_config']
connect_process = subprocess.Popen(connect_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
connect_output, connect_error = connect_process.communicate()

However, the process does not wait for completion, and communicate() executes instantly. As a result, connect_output and connect_error are empty. If I add a pause:

connect_command = ['ip', 'netns', 'exec', 'vpn_test_namespace', 'ipsec', 'up', 'vpn_test_config']
connect_process = subprocess.Popen(connect_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
time.sleep(3)
connect_output, connect_error = connect_process.communicate()

Or wait using a breakpoint, then everything is okay, and I see the result. What am I doing wrong?

I tried various methods recommended on StackOverflow or in Google, such as call(), check_call(), wait(), run(), but I was unable to achieve the desired result of making the script wait for the process to complete.

6
  • This is not what I expect. I guess ip is doing something funny, and that this cannot be reproduced with any other commands?
    – tripleee
    Commented Jul 10 at 7:56
  • ip netns creates a virtual environment for isolating network traffic, which is called network namespaces. So, in this case, the command "ip netns exec vpn_test_namespace ipsec up vpn_test_config" simply indicates that the VPN should be enabled in a specific namespace named "vpn_test_namespace".
    – Serg
    Commented Jul 10 at 8:09
  • The question is more like, does it perhaps spawn a separate subprocess and then let the parent die before the child has emitted any output, or some shenanigan like that?
    – tripleee
    Commented Jul 10 at 8:23
  • It could be like this, perhaps another child process is being created. But if so, how can I wait for all processes to finish, including all child processes? Because if I manually execute a command in the terminal, I clearly see that the input line is not available yet, as the command has not completed. Why can't I determine this using Python code?
    – Serg
    Commented Jul 10 at 8:31
  • 1
    If indeed this is what's happening I would look at whether ip could be fixed to not play tricks like that. I don't have a way to repro that here but I can speculate that something like a shell wrapper which runs it in the background and then waits might work.
    – tripleee
    Commented Jul 10 at 8:34

0

Browse other questions tagged or ask your own question.